Exclude X86_MPPARSE when either ACPI or SFI is present

2012-10-24 Thread Bin Gao

>From 6f439bdcc027fe9c0cb4ce2ca4f7d1879d84097d Mon Sep 17 00:00:00 2001
From: Bin Gao 
Date: Thu, 18 Oct 2012 16:13:46 -0700
Subject: [PATCH] arch/x86/Kconfig: not select X86_MPPARSE when SFI is present

MPS tables are not needed for systems that have proper ACPI support.
This is also true for systems that have SFI in place.

So this patch is to exclude X86_MPPARSE when either ACPI or SFI is present.

Signed-off-by: Bin Gao 
---
 arch/x86/Kconfig |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 46c3bff..b1494bd 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -310,7 +310,7 @@ config X86_X2APIC
  If you don't know what to do here, say N.
 
 config X86_MPPARSE
-   bool "Enable MPS table" if ACPI
+   bool "Enable MPS table" if ACPI || SFI
default y
depends on X86_LOCAL_APIC
---help---
-- 
1.7.4.4



arch/x86/Kconfig: not select X86_MPPARSE when SFI is present

2012-10-24 Thread Bin Gao
MPS tables are not needed for systems that have proper ACPI support.
This is also true for systems that have SFI in place.

So this patch is to exclude X86_MPPARSE when either ACPI or SFI is present.

Signed-off-by: Bin Gao 
---
 arch/x86/Kconfig |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 46c3bff..b1494bd 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -310,7 +310,7 @@ config X86_X2APIC
  If you don't know what to do here, say N.
 
 config X86_MPPARSE
-   bool "Enable MPS table" if ACPI
+   bool "Enable MPS table" if ACPI || SFI
default y
depends on X86_LOCAL_APIC
---help---
-- 
1.7.4.4

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


arch/x86/Kconfig: allow turning off CONFIG_X86_MPPARSE when either ACPI or SFI is present

2012-10-25 Thread Bin Gao
MPS tables are not needed for systems that have proper ACPI support.
This is also true for systems that have SFI in place.

So this patch allows the configuration (turning off) of CONFIG_X86_MPPARSE
when either ACPI or SFI is present.

Signed-off-by: Bin Gao 
---
 arch/x86/Kconfig |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 46c3bff..b1494bd 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -310,7 +310,7 @@ config X86_X2APIC
  If you don't know what to do here, say N.
 
 config X86_MPPARSE
-   bool "Enable MPS table" if ACPI
+   bool "Enable MPS table" if ACPI || SFI
default y
depends on X86_LOCAL_APIC
---help---
-- 
1.7.4.4

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


Re: arch/x86/Kconfig: not select X86_MPPARSE when SFI is present

2012-10-26 Thread Bin Gao
Yes, your suggested descriptions more match the change.
I'm sending a new patch for your review. Thanks.

-Bin

On Thu, Oct 25, 2012 at 09:57:52AM +0200, Ingo Molnar wrote:
> 
> * Bin Gao  wrote:
> 
> > MPS tables are not needed for systems that have proper ACPI support.
> > This is also true for systems that have SFI in place.
> > 
> > So this patch is to exclude X86_MPPARSE when either ACPI or SFI is present.
> > 
> > Signed-off-by: Bin Gao 
> > ---
> >  arch/x86/Kconfig |2 +-
> >  1 files changed, 1 insertions(+), 1 deletions(-)
> > 
> > diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> > index 46c3bff..b1494bd 100644
> > --- a/arch/x86/Kconfig
> > +++ b/arch/x86/Kconfig
> > @@ -310,7 +310,7 @@ config X86_X2APIC
> >   If you don't know what to do here, say N.
> >  
> >  config X86_MPPARSE
> > -   bool "Enable MPS table" if ACPI
> > +   bool "Enable MPS table" if ACPI || SFI
> > default y
> > depends on X86_LOCAL_APIC
> > ---help---
> 
> The changelog does not seem to match the patch. Did you want to 
> say:
> 
>   " So this patch allows the configuration (turning off) of
> CONFIG_X86_MPPARSE when either ACPI or SFI is present. "
> 
> ?
> 
>   Ingo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: i2c: introduce i2c helper i2c_find_client_by_name()

2013-06-14 Thread Bin Gao
On Fri, Jun 14, 2013 at 10:29:09AM +0300, Andy Shevchenko wrote:
> On Tue, Jun 11, 2013 at 8:11 PM, Bin Gao  wrote:
> > On Sun, Jun 09, 2013 at 10:53:35PM +0300, Andy Shevchenko wrote:
> >> Please, try to avoid top posting in the future emails.
> >>
> >> On Fri, Jun 7, 2013 at 12:26 AM, Bin Gao  wrote:
> >> > With v4l2, the camera sensor i2c devices are taken over by v4l2 master
> >> > driver, i.e. ISP driver, and are not expected to be accessed from
> >> > user sapce by ioctl. So ISP driver has to register them by itself to
> >> > get all related information for further communication. Please check
> >> > v4l2_i2c_new_subdev_board() in drivers/media/video/v4l2-common.c for 
> >> > details.
> >>
> >> Yes, this is legacy approach for non-DT/non-ACPI5 platforms.
> >
> > So what's the new approach for DT/ACPI5 platforms?
> 
> When DT or ACPI5 is enabled and used the devices are enumerated
> through corresponding frameworks in the kernel automatically. So, you
> get them initialized just after i2c host.

This is also true for SFI.
 
> >> > The platform code can definitely disallow calling 
> >> > i2c_register_board_info()
> >> > to register them but keep the i2c devices list and then let ISP driver 
> >> > register
> >> > them. But, problems come when a single kernel is going to run on two 
> >> > platforms
> >> > - one platform has ACPI5 and the other has SFI.
> >>
> >> You have to forget about SFI. Your ISP subdevices use plain platform
> >> data anyway.
> >
> > Why have to forget about SFI which is supported by upstream kernel?
> 
> It doesn't matter. Second sentence above is explained why. SFI,
> unfortunately, has few design flaws, that's why the information
> located there is not much useful in ISP case.

No, from device enumeration point of view, SFI is doing the same thing
as DT and ACPI5. I didn't see any flaws here.


> >> In ACPI 5 case v4l2 framework must be extended to cover that case.
> > To extend v4l2 framework is one of the options,
> 
> That is proper option.
> 
> > but this helper is also one
> > option.
> 
> I think this helper doesn't align to the current workflow.

Even you prefer to extend v4l2, you still need this helper.
The idea is just to move the unregister/register from a specific ISP driver
to v4l2.

I think you misunderstood my pionts somehow. Let me clarfiy a little bit:

Current solution:
1. Platform codes(on top of DT/ACPI5/SFI) don't call i2c_register_board_info(),
instead, prepare a table(kind of platform data) that has all camera i2c device 
information.
2. ISP driver registers devices listed in the table to i2c core - this makes 
sure
v4l2 takes over these devices.
The problem with this solution is that when a camera device runs on both ACPI5 
and
SFI, the platform codes will get a bit complicated and it's difficult to ensure 
one
binary kernel runs on both platforms(ACPI5 and SFI).
(To extend v4l2 with this solution doen't resolve my problem)

Solution I'm suggesting:
1. Let the platform codes call i2c_register_board_info() anyway.
2. Since ISP driver knows which camera devices it supports, so it simply 
unregisters
those devices (get the client by the introduced helper), then register it 
within v4l2.
This solution ensure one binary kernel can run on both platforms.
(To extend v4l2 with this solution could not be feasible, the device table is
ISP driver specific, not v4l2 specific)

> >> > The dynamic unregister and then
> >> > register based on this new helper will not have dependency on firmware 
> >> > interface -
> >> > the same platform code will work for all platforms.
> >>
> >> It's not a care of the ISP driver. I think you have to talk to Sakari
> >> about your issues.
> >
> > We have to do it in the ISP driver if we want one binary kernel
> > supporting multiple platforms.
> 
> What I'm talking about is not contradicting with that.
> 
> >> >> > A good example is that an ISP(Imaging Signal Processor) driver needs
> >> >> > register i2c camera sensor devices via v4l2, so it has to unregister
> >> >> > all i2c clients that were previously registered by calling
> >> >> > i2c_register_board_info(), and then re-register.
> 
> >> >> Why do you need to re-register them at run time?
> 
> Still this question is not answered.
> 
> 
> --
> With Best Regards,
> Andy Shevchenko
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


i2c: introduce i2c helper i2c_find_client_by_name()

2013-06-06 Thread Bin Gao
i2c: introduce i2c helper i2c_find_client_by_name()

There is a requirement to get the i2c_client pointer dynamically without
knowing the bus and slave address. But we do know the client name,
i.e. the name in the i2c_board_info. This patch is to fit this requirement.

A good example is that an ISP(Imaging Signal Processor) driver needs
register i2c camera sensor devices via v4l2, so it has to unregister
all i2c clients that were previously registered by calling
i2c_register_board_info(), and then re-register. For this case we
can use this helper to get i2c_client by passing the client name.

Signed-off-by: Bin Gao 
---
 drivers/i2c/i2c-core.c |   17 +
 include/linux/i2c.h|1 +
 2 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 48e31ed..17683de6 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -2326,6 +2326,23 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 
addr, unsigned short flags,
 }
 EXPORT_SYMBOL(i2c_smbus_xfer);
 
+static int match_name(struct device *dev, void *data)
+{
+   const char *name = data;
+   struct i2c_client *client = to_i2c_client(dev);
+
+   return !strncmp(client->name, name, strlen(client->name));
+}
+
+struct i2c_client *i2c_find_client_by_name(char *name)
+{
+   struct device *dev;
+
+   dev = bus_find_device(&i2c_bus_type, NULL, name, match_name);
+   return dev ? to_i2c_client(dev) : NULL;
+}
+EXPORT_SYMBOL_GPL(i2c_find_client_by_name);
+
 MODULE_AUTHOR("Simon G. Vogl ");
 MODULE_DESCRIPTION("I2C-Bus main module");
 MODULE_LICENSE("GPL");
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index e988fa9..7d8bf02 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -509,6 +509,7 @@ extern void i2c_clients_command(struct i2c_adapter *adap,
 extern struct i2c_adapter *i2c_get_adapter(int nr);
 extern void i2c_put_adapter(struct i2c_adapter *adap);
 
+extern struct i2c_client *i2c_find_client_by_name(char *name);
 
 /* Return the functionality mask */
 static inline u32 i2c_get_functionality(struct i2c_adapter *adap)
-- 
1.7.4.4

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


Re: i2c: introduce i2c helper i2c_find_client_by_name()

2013-06-06 Thread Bin Gao
With v4l2, the camera sensor i2c devices are taken over by v4l2 master
driver, i.e. ISP driver, and are not expected to be accessed from
user sapce by ioctl. So ISP driver has to register them by itself to
get all related information for further communication. Please check
v4l2_i2c_new_subdev_board() in drivers/media/video/v4l2-common.c for details.

The platform code can definitely disallow calling i2c_register_board_info()
to register them but keep the i2c devices list and then let ISP driver register
them. But, problems come when a single kernel is going to run on two platforms
- one platform has ACPI5 and the other has SFI. The dynamic unregister and then
register based on this new helper will not have dependency on firmware 
interface -
the same platform code will work for all platforms.

On Thu, Jun 06, 2013 at 11:32:06PM +0300, Andy Shevchenko wrote:
> On Thu, Jun 6, 2013 at 9:33 PM, Bin Gao  wrote:
> > There is a requirement to get the i2c_client pointer dynamically without
> > knowing the bus and slave address. But we do know the client name,
> > i.e. the name in the i2c_board_info. This patch is to fit this requirement.
> >
> > A good example is that an ISP(Imaging Signal Processor) driver needs
> > register i2c camera sensor devices via v4l2, so it has to unregister
> > all i2c clients that were previously registered by calling
> > i2c_register_board_info(), and then re-register. For this case we
> > can use this helper to get i2c_client by passing the client name.
> 
> Why ISP driver would like to register sensor drivers in the first place?
> That seems the task of platform code, or DT, or ACPI5
> 
> Why do you need to re-register them at run time?
> 
> --
> With Best Regards,
> Andy Shevchenko
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: i2c: introduce i2c helper i2c_find_client_by_name()

2013-06-21 Thread Bin Gao

On 6/19/2013 3:13 AM, Wolfram Sang wrote:



Even you prefer to extend v4l2, you still need this helper.
The idea is just to move the unregister/register from a specific ISP driver
to v4l2.

I think you misunderstood my pionts somehow. Let me clarfiy a little bit:

Current solution:
1. Platform codes(on top of DT/ACPI5/SFI) don't call i2c_register_board_info(),
instead, prepare a table(kind of platform data) that has all camera i2c device 
information.
2. ISP driver registers devices listed in the table to i2c core - this makes 
sure
v4l2 takes over these devices.
The problem with this solution is that when a camera device runs on both ACPI5 
and
SFI, the platform codes will get a bit complicated and it's difficult to ensure 
one
binary kernel runs on both platforms(ACPI5 and SFI).
(To extend v4l2 with this solution doen't resolve my problem)

Solution I'm suggesting:
1. Let the platform codes call i2c_register_board_info() anyway.
2. Since ISP driver knows which camera devices it supports, so it simply 
unregisters
those devices (get the client by the introduced helper), then register it 
within v4l2.
This solution ensure one binary kernel can run on both platforms.
(To extend v4l2 with this solution could not be feasible, the device table is
ISP driver specific, not v4l2 specific)


I also wonder about the need to unregister. I have to admit I don't know
much about I2C handling in v4l2. But if it requires unregistering from
i2c core and registering to v4l2 core, then it sounds to me like we
could check if there is a more fundamential cleanup needed? Deferring
for now, looks like an issue worth looking at, yet there are other
things in the queue first.



Platform codes are supposed to call i2c_register_board_info() or 
i2c_new_device() to register devices, we don't want to change this.
Not sure v4l2 can still take over the devices without 
unregistering/registering. Need look deeply into the v4l2 code...


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


Re: i2c: introduce i2c helper i2c_find_client_by_name()

2013-06-11 Thread Bin Gao
On Sun, Jun 09, 2013 at 10:53:35PM +0300, Andy Shevchenko wrote:
> Please, try to avoid top posting in the future emails.
> 
> On Fri, Jun 7, 2013 at 12:26 AM, Bin Gao  wrote:
> > With v4l2, the camera sensor i2c devices are taken over by v4l2 master
> > driver, i.e. ISP driver, and are not expected to be accessed from
> > user sapce by ioctl. So ISP driver has to register them by itself to
> > get all related information for further communication. Please check
> > v4l2_i2c_new_subdev_board() in drivers/media/video/v4l2-common.c for 
> > details.
> 
> Yes, this is legacy approach for non-DT/non-ACPI5 platforms.

So what's the new approach for DT/ACPI5 platforms?

> 
> > The platform code can definitely disallow calling i2c_register_board_info()
> > to register them but keep the i2c devices list and then let ISP driver 
> > register
> > them. But, problems come when a single kernel is going to run on two 
> > platforms
> > - one platform has ACPI5 and the other has SFI.
> 
> You have to forget about SFI. Your ISP subdevices use plain platform
> data anyway.

Why have to forget about SFI which is supported by upstream kernel?

> In ACPI 5 case v4l2 framework must be extended to cover that case.

To extend v4l2 framework is one of the options, but this helper is also one
option.

> > The dynamic unregister and then
> > register based on this new helper will not have dependency on firmware 
> > interface -
> > the same platform code will work for all platforms.
> 
> It's not a care of the ISP driver. I think you have to talk to Sakari
> about your issues.

We have to do it in the ISP driver if we want one binary kernel
supporting multiple platforms.

> > On Thu, Jun 06, 2013 at 11:32:06PM +0300, Andy Shevchenko wrote:
> >> On Thu, Jun 6, 2013 at 9:33 PM, Bin Gao  wrote:
> >> > There is a requirement to get the i2c_client pointer dynamically without
> >> > knowing the bus and slave address. But we do know the client name,
> >> > i.e. the name in the i2c_board_info. This patch is to fit this 
> >> > requirement.
> >> >
> >> > A good example is that an ISP(Imaging Signal Processor) driver needs
> >> > register i2c camera sensor devices via v4l2, so it has to unregister
> >> > all i2c clients that were previously registered by calling
> >> > i2c_register_board_info(), and then re-register. For this case we
> >> > can use this helper to get i2c_client by passing the client name.
> >>
> >> Why ISP driver would like to register sensor drivers in the first place?
> >> That seems the task of platform code, or DT, or ACPI5
> >>
> >> Why do you need to re-register them at run time?
> 
> --
> With Best Regards,
> Andy Shevchenko
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: x86/pci/mrst: force all pci config toward 0:0:0, 0:2:0 and 0:3:0 to type 1

2013-05-01 Thread Bin Gao
On Wed, May 01, 2013 at 11:17:10AM -0600, Bjorn Helgaas wrote:
> Is there any possibility of multi-function devices at bus 0, device 0, 2, or 
> 3?
> 
> What about bridges -- can any of these be a bridge?
> 
> If either of those could happen, these checks could be too specific.
0:2:0 and 0:3:0 are the only 2 devices behind the bridge 0:0:0.
These devices don't implement pcie capability list in legacy config space
so no offset above 255 would be triggered.
The fixed bar pcie capability located at 0x100 is for pci-shimed device
only, not for 0, 2 and 3. But current implementation applies it to 0,
2 and 3 as well. This is what the patch is going to address.

> 
> Is there a doc that identifies these cases where config mechanism #1
> should be used instead of MMCONFIG?
Unfortunately no doc identifies this.
But since FW doesn't provide pci shim for device 0, 2 and 3,
and these 3 real pci devices have only 256 bytes legacy pci
config space so they can only be accessed by type 1.

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


Re: x86/pci/mrst: force all pci config toward 0:0:0, 0:2:0 and 0:3:0 to type 1

2013-05-06 Thread Bin Gao
On Mon, May 06, 2013 at 10:38:55AM -0700, Bjorn Helgaas wrote:
> Please use the conventional Linux PCI address formatting
> (:BB:dd.f, where  = domain (optional, often omitted if  ==
> 0), BB = bus, dd = device, f = function), because this is quite
> confusing.
Yes, will do.

> You say "0:2:0 and 0:3:0" are behind the bridge "0:0:0", but the patch
> you sent clearly applies only to devices on bus 0.  The patch applies
> to devices 00:00.0, 00:02.0, and 00:03.0.  These are all on the same
> bus, so none of them can be behind a bridge.
Sorry my bad, "behind" could be confusing(or wrong:-)).
:00:00.0 is the host bridge, :00:02.0 and :00:03.0 are
the 2 devices on bus 00. So these 3 devides are on the same bus.

> If the 00:00.0 device is in fact a bridge, its secondary bus will be
> something other than 0, so any devices behind the bridge will be on a
> non-zero bus number.  And I assume you would want to use config
> mechanism #1 to reach those devices, too.  Your current patch doesn't
> do that -- it only applies to devices on bus 0.
No pci-pci bridge, no secondary bus (see above explanation).
:00:00.0 (host bridge), :00:02.0 and :00:03.0 are the only
3 real pci devices in the chip.
 
> I dropped this patch until this gets straightened out.
Will re-submit together with other cleanup for the same file. Thanks.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: x86/pci/mrst: force all pci config toward 0:0:0, 0:2:0 and 0:3:0 to type 1

2013-05-06 Thread Bin Gao
On Mon, May 06, 2013 at 11:56:38AM -0700, Bjorn Helgaas wrote:
> I hate it when I go to the trouble of reviewing something and asking
> relevant questions, and then people ignore the questions :(
Sorry for that.
 
> I'd still like to know whether multi-function devices are possible at
> bus 0, device 0, 2, or 3.
:00:00.0 is host bridge.
:00:02.0 and :00:03.0 are single-function devices.

> Are these devices built-in, so you know exactly what they are and they
> can never be anything else? 
Yes, they are built-in devices and I know exactly what they are.

> Or is there a slot or other way to connect a user-chosen device?
No, not that way.

> If you included "lspci -vv" output, that would make this much easier
> to talk about.
I'm sorry the busybox shrinks lspci options so it doesn't have
meaningful ouput excpet for DID:VID and class code.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


x86/pci/mrst: force all pci config toward 0:0:0, 0:2:0 and 0:3:0 to type 1

2013-04-30 Thread Bin Gao
x86/pci/mrst: force all pci config access toward 0:0:0, 0:2:0 and 0:3:0 to type 
1

For real pci devices 0:0:0, 0:2:0 and 0:3:0, there is either no pci shim, or
no guarantee of data correctness of offset 256-4k. So for whatever reason,
Linux kernel should not do MMCFG pci config access to those devices. Instead,
always use type 1 for those devices.

Signed-off-by: Bin Gao 
---
 arch/x86/pci/mrst.c |   10 ++
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/x86/pci/mrst.c b/arch/x86/pci/mrst.c
index 6eb18c4..0e0fabf 100644
--- a/arch/x86/pci/mrst.c
+++ b/arch/x86/pci/mrst.c
@@ -141,6 +141,11 @@ static int pci_device_update_fixed(struct pci_bus *bus, 
unsigned int devfn,
  */
 static bool type1_access_ok(unsigned int bus, unsigned int devfn, int reg)
 {
+   if (bus == 0 && (devfn == PCI_DEVFN(2, 0)
+   || devfn == PCI_DEVFN(0, 0)
+   || devfn == PCI_DEVFN(3, 0)))
+   return 1;
+
/* This is a workaround for A0 LNC bug where PCI status register does
 * not have new CAP bit set. can not be written by SW either.
 *
@@ -150,10 +155,7 @@ static bool type1_access_ok(unsigned int bus, unsigned int 
devfn, int reg)
 */
if (reg >= 0x100 || reg == PCI_STATUS || reg == PCI_HEADER_TYPE)
return 0;
-   if (bus == 0 && (devfn == PCI_DEVFN(2, 0)
-   || devfn == PCI_DEVFN(0, 0)
-   || devfn == PCI_DEVFN(3, 0)))
-   return 1;
+
return 0; /* langwell on others */
 }
 
-- 
1.7.4.4

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


[PATCH v6] gpio: add Intel WhiskeyCove PMIC GPIO driver

2016-07-19 Thread Bin Gao
This patch introduces a separate GPIO driver for Intel WhiskeyCove PMIC.
This driver is based on gpio-crystalcove.c.

Signed-off-by: Ajay Thomas 
Signed-off-by: Bin Gao 
Reviewed-by: Andy Shevchenko 
Reviewed-by: Mika Westerberg 
---
Changes in v6:
 - Removed unnecessary wcove_gpio_remove()
 - Used devm_gpiochip_remove() instead of gpiochip_remove()
 - Various coding style changes per Mika's comment
Changes in v5:
 - Revisited the interrupt handler code to iterate until all pending
   interrupts are handled. This change is to avoid missing interrupt
   when we're inside the interrupt handler.
 - Used regmap_bulk_read() to read address adjacent registers.
Changes in v4:
 - Converted CTLI_INTCNT_XX macros to less verbose ones INT_DETECT_XX.
 - Add comments about why there is no .pm for the driver.
 - Header files re-ordered.
 - Various coding style change to address Andy's comments.
Changes in v3:
 - Fixed the year in copyright line(2015-->2016).
 - Removed DRV_NAME macro.
 - Added kernel-doc for regmap_irq_chip of the wcove_gpio structure.
 - Line length fix.
Changes in v2:
 - Typo fix (Whsikey --> Whiskey).
 - Included linux/gpio/driver.h instead of linux/gpio.h
 - Implemented .set_single_ended().
 - Added GPIO register description.
 - Replaced container_of() with gpiochip_get_data().
 - Removed unnecessary "if (gpio > WCOVE_VGPIO_NUM" check.
 - Removed the device id table and added MODULE_ALIAS().
 drivers/gpio/Kconfig  |  13 ++
 drivers/gpio/Makefile |   1 +
 drivers/gpio/gpio-wcove.c | 439 ++
 3 files changed, 453 insertions(+)
 create mode 100644 drivers/gpio/gpio-wcove.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 536112f..0f33982 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -806,6 +806,19 @@ config GPIO_CRYSTAL_COVE
  This driver can also be built as a module. If so, the module will be
  called gpio-crystalcove.
 
+config GPIO_WHISKEY_COVE
+   tristate "GPIO support for Whiskey Cove PMIC"
+   depends on INTEL_SOC_PMIC
+   select GPIOLIB_IRQCHIP
+   help
+ Support for GPIO pins on Whiskey Cove PMIC.
+
+ Say Yes if you have a Intel SoC based tablet with Whiskey Cove PMIC
+ inside.
+
+ This driver can also be built as a module. If so, the module will be
+ called gpio-wcove.
+
 config GPIO_CS5535
tristate "AMD CS5535/CS5536 GPIO support"
depends on MFD_CS5535
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 991598e..fff6914 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_GPIO_BT8XX)  += gpio-bt8xx.o
 obj-$(CONFIG_GPIO_CLPS711X)+= gpio-clps711x.o
 obj-$(CONFIG_GPIO_CS5535)  += gpio-cs5535.o
 obj-$(CONFIG_GPIO_CRYSTAL_COVE)+= gpio-crystalcove.o
+obj-$(CONFIG_GPIO_WHISKEY_COVE)+= gpio-wcove.o
 obj-$(CONFIG_GPIO_DA9052)  += gpio-da9052.o
 obj-$(CONFIG_GPIO_DA9055)  += gpio-da9055.o
 obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o
diff --git a/drivers/gpio/gpio-wcove.c b/drivers/gpio/gpio-wcove.c
new file mode 100644
index 000..dc586e5
--- /dev/null
+++ b/drivers/gpio/gpio-wcove.c
@@ -0,0 +1,439 @@
+/*
+ * gpio-wcove.c - Intel Whiskey Cove GPIO Driver
+ *
+ * This driver is written based on gpio-crystalcove.c
+ *
+ * Copyright (C) 2016 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * Whiskey Cove PMIC has 13 physical GPIO pins divided into 3 banks:
+ * Bank 0: Pin 0 - 6
+ * Bank 1: Pin 7 - 10
+ * Bank 2: Pin 11 -12
+ * Each pin has one output control register and one input control register.
+ */
+#define BANK0_NR_PINS  7
+#define BANK1_NR_PINS  4
+#define BANK2_NR_PINS  2
+#define WCOVE_GPIO_NUM (BANK0_NR_PINS + BANK1_NR_PINS + BANK2_NR_PINS)
+#define WCOVE_VGPIO_NUM94
+/* GPIO output control registers(one per pin): 0x4e44 - 0x4e50 */
+#define GPIO_OUT_CTRL_BASE 0x4e44
+/* GPIO input control registers(one per pin): 0x4e51 - 0x4e5d */
+#define GPIO_IN_CTRL_BASE  0x4e51
+
+/*
+ * GPIO interrupts are organized in two groups:
+ * Group 0: Bank 0 pins (Pin 0 - 6)
+ * Group 1: Bank 1 and Bank 2 pins (Pin 7 - 12)
+ * Each group has two registers(one bit per pin): status and mask.
+ */
+#define GROUP0_NR_IRQS 7
+#define GROUP1_NR_IRQS 6
+#define IRQ_MASK_BASE  0x4e19
+#define IRQ_STAT

[PATCH v3] thermal: add Intel BXT WhiskeyCove PMIC thermal driver

2016-07-20 Thread Bin Gao
From: Yegnesh S Iyer 

This change adds support for Intel BXT Whiskey Cove PMIC thermal
driver which is intended to handle the alert interrupts triggered
upon thermal trip point cross and notify the thermal framework
appropriately with the zone, temp, crossed trip and event details.

Signed-off-by: Yegnesh S Iyer 
Signed-off-by: Bin Gao 
Changes in v3:
 - Moved driver data from mfd domain to the driver
 - Minor coding style related cleanup
Changes in v2:
 - Removed unnecessary request_threaded_irq() - we should be only
   using devm_request_threaded_irq() with virq
---
 drivers/thermal/Kconfig  |  10 ++
 drivers/thermal/Makefile |   1 +
 drivers/thermal/intel_pmic_thermal.c | 299 +++
 3 files changed, 310 insertions(+)
 create mode 100644 drivers/thermal/intel_pmic_thermal.c

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 2d702ca..9065ba7 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -332,6 +332,16 @@ menu "ACPI INT340X thermal drivers"
 source drivers/thermal/int340x_thermal/Kconfig
 endmenu
 
+config INTEL_PMIC_THERMAL
+   tristate "Intel PMIC thermal driver"
+   depends on X86 && INTEL_SOC_PMIC && REGMAP
+   help
+ Select this driver for Intel PMIC with ADC channels monitoring system
+ temperature measurements and alerts.
+ This driver is used for monitoring the ADC channels of PMIC and 
handles
+ the alert trip point interrupts and notifies the thermal framework 
with
+ the trip point and temperature details of the zone.
+
 config INTEL_PCH_THERMAL
tristate "Intel PCH Thermal Reporting Driver"
depends on X86 && PCI
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 10b07c1..159efcc 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_INTEL_SOC_DTS_THERMAL)   += 
intel_soc_dts_thermal.o
 obj-$(CONFIG_INTEL_QUARK_DTS_THERMAL)  += intel_quark_dts_thermal.o
 obj-$(CONFIG_TI_SOC_THERMAL)   += ti-soc-thermal/
 obj-$(CONFIG_INT340X_THERMAL)  += int340x_thermal/
+obj-$(CONFIG_INTEL_PMIC_THERMAL) += intel_pmic_thermal.o
 obj-$(CONFIG_INTEL_PCH_THERMAL)+= intel_pch_thermal.o
 obj-$(CONFIG_ST_THERMAL)   += st/
 obj-$(CONFIG_TEGRA_SOCTHERM)   += tegra/
diff --git a/drivers/thermal/intel_pmic_thermal.c 
b/drivers/thermal/intel_pmic_thermal.c
new file mode 100644
index 000..401e7a7
--- /dev/null
+++ b/drivers/thermal/intel_pmic_thermal.c
@@ -0,0 +1,299 @@
+/*
+ * pmic_thermal.c - PMIC thermal driver
+ *
+ * Copyright (C) 2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define BXTWC_THRM0IRQ 0x4E04
+#define BXTWC_THRM1IRQ 0x4E05
+#define BXTWC_THRM2IRQ 0x4E06
+#define BXTWC_MTHRM0IRQ0x4E12
+#define BXTWC_MTHRM1IRQ0x4E13
+#define BXTWC_MTHRM2IRQ0x4E14
+#define BXTWC_STHRM0IRQ0x4F19
+#define BXTWC_STHRM1IRQ0x4F1A
+#define BXTWC_STHRM2IRQ0x4F1B
+
+struct trip_config_map {
+   u16 irq_reg;
+   u16 irq_en;
+   u16 evt_stat;
+   u8 irq_mask;
+   u8 irq_en_mask;
+   u8 evt_mask;
+   u8 trip_num;
+};
+
+struct thermal_irq_map {
+   char handle[20];
+   int num_trips;
+   struct trip_config_map *trip_config;
+};
+
+struct pmic_thermal_data {
+   struct thermal_irq_map *maps;
+   int num_maps;
+};
+
+static struct trip_config_map bxtwc_str0_trip_config[] = {
+   {
+   .irq_reg = BXTWC_THRM0IRQ,
+   .irq_mask = 0x01,
+   .irq_en = BXTWC_MTHRM0IRQ,
+   .irq_en_mask = 0x01,
+   .evt_stat = BXTWC_STHRM0IRQ,
+   .evt_mask = 0x01,
+   .trip_num = 0
+   },
+   {
+   .irq_reg = BXTWC_THRM0IRQ,
+   .irq_mask = 0x10,
+   .irq_en = BXTWC_MTHRM0IRQ,
+   .irq_en_mask = 0x10,
+   .evt_stat = BXTWC_STHRM0IRQ,
+   .evt_mask = 0x10,
+   .trip_num = 1
+   }
+};
+
+static struct trip_config_map bxtwc_str1_trip_config[] = {
+   {
+   .irq_reg = BXTWC_THRM0IRQ,
+   .irq_mask = 0x02,
+   .irq_en = BXTWC_MTHRM0IRQ,
+   .irq_en_mask = 0x02,
+   .evt_stat = BXTWC_STHRM0IRQ,
+

Re: [PATCH v4] mfd: intel_soc_pmic_bxtwc: Add Intel BXT WhiskeyCove PMIC ADC thermal channel mapping and USB type-C resources

2016-07-20 Thread Bin Gao
On Tue, Jun 28, 2016 at 03:58:49PM +0100, Lee Jones wrote:
> On Mon, 27 Jun 2016, Bin Gao wrote:
> 
> > This patch adds the mapping of PMIC ADC channel to thermal zone and
> > USB type-C resources. This mapping is used in the pmic thermal driver
> > to notify the thermal zone with the pmic adc channel alert interrupts.
> 
> > This patch also adds three new data structures to
> > include/linux/mfd/intel_soc_pmic.h: struct trip_config_map{},
> > struct thermal_irq_map {} and struct pmic_thermal_data {} which are
> > required by changes we did on intel_soc_pmic_bxtwc.c.
> 
> No need for this section.
> 
> > Signed-off-by: Yegnesh S Iyer 
> > Signed-off-by: Rohit S Kenchanpura 
> > Signed-off-by: Bin Gao 
> > ---
> > Changes in v4:
> >  - Extended existing regmap reg instead of defining a new one:
> >REGMAP_IRQ_REG(BXTWC_CHGR0_IRQ, 5, 0x3f)
> > Changes in v3:
> >  - Added USB type-C resources.
> > Changes in v2:
> >  - Fixed subject line.
> >  - Combined two patches into one.
> >  drivers/mfd/intel_soc_pmic_bxtwc.c | 126 
> > -
> >  include/linux/mfd/intel_soc_pmic.h |  21 +++
> >  2 files changed, 146 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c 
> > b/drivers/mfd/intel_soc_pmic_bxtwc.c
> > index b942876..e69eb86 100644
> > --- a/drivers/mfd/intel_soc_pmic_bxtwc.c
> > +++ b/drivers/mfd/intel_soc_pmic_bxtwc.c
> > @@ -47,6 +47,8 @@
> >  #define BXTWC_MIRQLVL1 0x4E0E
> >  #define BXTWC_MPWRTNIRQ0x4E0F
> >  
> > +#define BXTWC_MIRQLVL1_MCHGR   BIT(5)
> > +
> 
> This line looks very much out of place here.
> 
> >  #define BXTWC_MTHRM0IRQ0x4E12
> >  #define BXTWC_MTHRM1IRQ0x4E13
> >  #define BXTWC_MTHRM2IRQ0x4E14
> > @@ -58,6 +60,10 @@
> >  #define BXTWC_MGPIO1IRQ0x4E1A
> >  #define BXTWC_MCRITIRQ 0x4E1B
> >  
> > +#define BXTWC_STHRM0IRQ0x4F19
> > +#define BXTWC_STHRM1IRQ0x4F1A
> > +#define BXTWC_STHRM2IRQ0x4F1B
> > +
> >  /* Whiskey Cove PMIC share same ACPI ID between different platforms */
> >  #define BROXTON_PMIC_WC_HRV4
> >  
> > @@ -109,13 +115,116 @@ static const struct regmap_irq 
> > bxtwc_regmap_irqs_level2[] = {
> > REGMAP_IRQ_REG(BXTWC_THRM2_IRQ, 2, 0xff),
> > REGMAP_IRQ_REG(BXTWC_BCU_IRQ, 3, 0x1f),
> > REGMAP_IRQ_REG(BXTWC_ADC_IRQ, 4, 0xff),
> > -   REGMAP_IRQ_REG(BXTWC_CHGR0_IRQ, 5, 0x1f),
> > +   REGMAP_IRQ_REG(BXTWC_CHGR0_IRQ, 5, 0x3f),
> 
> Is the original code wrong?
> 
> If so, it's a fix and needs it's own patch
> .
> > REGMAP_IRQ_REG(BXTWC_CHGR1_IRQ, 6, 0x1f),
> > REGMAP_IRQ_REG(BXTWC_GPIO0_IRQ, 7, 0xff),
> > REGMAP_IRQ_REG(BXTWC_GPIO1_IRQ, 8, 0x3f),
> > REGMAP_IRQ_REG(BXTWC_CRIT_IRQ, 9, 0x03),
> >  };
> >  
> > +static struct trip_config_map str0_trip_config[] = {
> > +   {
> > +   .irq_reg = BXTWC_THRM0IRQ,
> > +   .irq_mask = 0x01,
> > +   .irq_en = BXTWC_MTHRM0IRQ,
> > +   .irq_en_mask = 0x01,
> > +   .evt_stat = BXTWC_STHRM0IRQ,
> > +   .evt_mask = 0x01,
> > +   .trip_num = 0
> > +   },
> > +   {
> > +   .irq_reg = BXTWC_THRM0IRQ,
> > +   .irq_mask = 0x10,
> > +   .irq_en = BXTWC_MTHRM0IRQ,
> > +   .irq_en_mask = 0x10,
> > +   .evt_stat = BXTWC_STHRM0IRQ,
> > +   .evt_mask = 0x10,
> > +   .trip_num = 1
> > +   }
> > +};
> > +
> > +static struct trip_config_map str1_trip_config[] = {
> > +   {
> > +   .irq_reg = BXTWC_THRM0IRQ,
> > +   .irq_mask = 0x02,
> > +   .irq_en = BXTWC_MTHRM0IRQ,
> > +   .irq_en_mask = 0x02,
> > +   .evt_stat = BXTWC_STHRM0IRQ,
> > +   .evt_mask = 0x02,
> > +   .trip_num = 0
> > +   },
> > +   {
> > +   .irq_reg = BXTWC_THRM0IRQ,
> > +   .irq_mask = 0x20,
> > +   .irq_en = BXTWC_MTHRM0IRQ,
> > +   .irq_en_mask = 0x20,
> > +   .evt_stat = BXTWC_STHRM0IRQ,
> > +   .evt_mask = 0x20,
> > +   .trip_num = 1
> > +   },
> > +};
> > +
> > +static struct trip_config_map str2_trip_config[] = {
> > +   {
> > +   .irq_reg = BXTWC_THRM0IRQ,
> > +   .irq_mask = 0x04,
> > +   .i

[PATCH] mfd: intel_soc_pmic_bxtwc: add bxt_wcove_usbc device

2016-07-20 Thread Bin Gao
The Intel Whiskey Cove PMIC includes several function units, e.g.
ADC, thermal, USB Type-C, GPIO, etc. The corresponding device has
to be created in the mfd driver(intel_soc_pmic_bxtwc.c). This change
adds the USB Type-c device.

Signed-off-by: Bin Gao 
---
 drivers/mfd/intel_soc_pmic_bxtwc.c | 23 ++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c 
b/drivers/mfd/intel_soc_pmic_bxtwc.c
index b942876..43e54b7 100644
--- a/drivers/mfd/intel_soc_pmic_bxtwc.c
+++ b/drivers/mfd/intel_soc_pmic_bxtwc.c
@@ -47,6 +47,8 @@
 #define BXTWC_MIRQLVL1 0x4E0E
 #define BXTWC_MPWRTNIRQ0x4E0F
 
+#define BXTWC_MIRQLVL1_MCHGR   BIT(5)
+
 #define BXTWC_MTHRM0IRQ0x4E12
 #define BXTWC_MTHRM1IRQ0x4E13
 #define BXTWC_MTHRM2IRQ0x4E14
@@ -109,7 +111,7 @@ static const struct regmap_irq bxtwc_regmap_irqs_level2[] = 
{
REGMAP_IRQ_REG(BXTWC_THRM2_IRQ, 2, 0xff),
REGMAP_IRQ_REG(BXTWC_BCU_IRQ, 3, 0x1f),
REGMAP_IRQ_REG(BXTWC_ADC_IRQ, 4, 0xff),
-   REGMAP_IRQ_REG(BXTWC_CHGR0_IRQ, 5, 0x1f),
+   REGMAP_IRQ_REG(BXTWC_CHGR0_IRQ, 5, 0x3f),
REGMAP_IRQ_REG(BXTWC_CHGR1_IRQ, 6, 0x1f),
REGMAP_IRQ_REG(BXTWC_GPIO0_IRQ, 7, 0xff),
REGMAP_IRQ_REG(BXTWC_GPIO1_IRQ, 8, 0x3f),
@@ -143,6 +145,10 @@ static struct resource adc_resources[] = {
DEFINE_RES_IRQ_NAMED(BXTWC_ADC_IRQ, "ADC"),
 };
 
+static struct resource usbc_resources[] = {
+   DEFINE_RES_IRQ_NAMED(BXTWC_CHGR0_IRQ, "USBC"),
+};
+
 static struct resource charger_resources[] = {
DEFINE_RES_IRQ_NAMED(BXTWC_CHGR0_IRQ, "CHARGER"),
DEFINE_RES_IRQ_NAMED(BXTWC_CHGR1_IRQ, "CHARGER1"),
@@ -170,6 +176,11 @@ static struct mfd_cell bxt_wc_dev[] = {
.resources = thermal_resources,
},
{
+   .name = "bxt_wcove_usbc",
+   .num_resources = ARRAY_SIZE(usbc_resources),
+   .resources = usbc_resources,
+   },
+   {
.name = "bxt_wcove_ext_charger",
.num_resources = ARRAY_SIZE(charger_resources),
.resources = charger_resources,
@@ -403,6 +414,16 @@ static int bxtwc_probe(struct platform_device *pdev)
goto err_sysfs;
}
 
+   /*
+* There is known hw bug. Upon reset BIT 5 of register
+* BXTWC_CHGR_LVL1_IRQ is 0 which is the expected value. However,
+* later it's set to 1(masked) automatically by hardware. So we
+* have the software workaround here to unmaksed it in order to let
+* charger interrutp work.
+*/
+   regmap_update_bits(pmic->regmap, BXTWC_MIRQLVL1,
+   BXTWC_MIRQLVL1_MCHGR, 0);
+
return 0;
 
 err_sysfs:
-- 
1.9.1



Re: [PATCH v2] gpio: add Intel WhiskeyCove GPIO driver

2016-06-19 Thread Bin Gao
> 
> Looks good. I have couple of minor comments, see below.
Thanks for review again.

> 
> > + * Copyright (C) 2015 Intel Corporation. All rights reserved.
> 
> It is 2016 now isn't it? :-)
Will fix this in v3.

> > +#define DRV_NAME "bxt_wcove_gpio"
> 
> Drop this.
We have _TWO_ places using DRV_NAME(near the end of the file):
static struct platform_driver wcove_gpio_driver = {
   .driver = {
   .name = DRV_NAME,
   },

and

MODULE_ALIAS("platform:" DRV_NAME);

You are suggesting to replace DRV_NAME with bxt_wcove_gpio(but why?)
or something else?

> > + * struct wcove_gpio - Whiskey Cove GPIO controller
> > + * @buslock: for bus lock/sync and unlock.
> > + * @chip: the abstract gpio_chip structure.
> > + * @regmap: the regmap from the parent device.
> 
> Missing kernel-doc for regmap_irq_chip.
Will fix this in v3.

> > +static void wcove_update_irq_mask(struct wcove_gpio *wg,
> > +   int gpio)
> 
> Does this with into 80 chars?
Yes, it fits into 80 chars. Will fix in v3.



Re: [PATCH v2] mfd: intel_soc_pmic_bxtwc: Add Intel BXT WhiskeyCove PMIC ADC thermal channel-zone mapping

2016-06-19 Thread Bin Gao
On Fri, Jun 17, 2016 at 09:01:59AM +0100, Lee Jones wrote:
> > +static struct trip_config_map str0_trip_config[] = {
> > +   {
> > +   .irq_reg = BXTWC_THRM0IRQ,
> > +   .irq_mask = 0x01,
> > +   .irq_en = BXTWC_MTHRM0IRQ,
> > +   .irq_en_mask = 0x01,
> > +   .evt_stat = BXTWC_STHRM0IRQ,
> > +   .evt_mask = 0x01,
> > +   .trip_num = 0
> > +   },
> > +   {
> > +   .irq_reg = BXTWC_THRM0IRQ,
> > +   .irq_mask = 0x10,
> > +   .irq_en = BXTWC_MTHRM0IRQ,
> > +   .irq_en_mask = 0x10,
> > +   .evt_stat = BXTWC_STHRM0IRQ,
> > +   .evt_mask = 0x10,
> > +   .trip_num = 1
> > +   }
> > +};
> > +
> > +static struct trip_config_map str1_trip_config[] = {
> > +   {
> > +   .irq_reg = BXTWC_THRM0IRQ,
> > +   .irq_mask = 0x02,
> > +   .irq_en = BXTWC_MTHRM0IRQ,
> > +   .irq_en_mask = 0x02,
> > +   .evt_stat = BXTWC_STHRM0IRQ,
> > +   .evt_mask = 0x02,
> > +   .trip_num = 0
> > +   },
> > +   {
> > +   .irq_reg = BXTWC_THRM0IRQ,
> > +   .irq_mask = 0x20,
> > +   .irq_en = BXTWC_MTHRM0IRQ,
> > +   .irq_en_mask = 0x20,
> > +   .evt_stat = BXTWC_STHRM0IRQ,
> > +   .evt_mask = 0x20,
> > +   .trip_num = 1
> > +   },
> > +};
> > +
> > +static struct trip_config_map str2_trip_config[] = {
> > +   {
> > +   .irq_reg = BXTWC_THRM0IRQ,
> > +   .irq_mask = 0x04,
> > +   .irq_en = BXTWC_MTHRM0IRQ,
> > +   .irq_en_mask = 0x04,
> > +   .evt_stat = BXTWC_STHRM0IRQ,
> > +   .evt_mask = 0x04,
> > +   .trip_num = 0
> > +   },
> > +   {
> > +   .irq_reg = BXTWC_THRM0IRQ,
> > +   .irq_mask = 0x40,
> > +   .irq_en = BXTWC_MTHRM0IRQ,
> > +   .irq_en_mask = 0x40,
> > +   .evt_stat = BXTWC_STHRM0IRQ,
> > +   .evt_mask = 0x40,
> > +   .trip_num = 1
> > +   },
> > +};
> > +
> > +static struct trip_config_map str3_trip_config[] = {
> > +   {
> > +   .irq_reg = BXTWC_THRM2IRQ,
> > +   .irq_mask = 0x10,
> > +   .irq_en = BXTWC_MTHRM2IRQ,
> > +   .irq_en_mask = 0x10,
> > +   .evt_stat = BXTWC_STHRM2IRQ,
> > +   .evt_mask = 0x10,
> > +   .trip_num = 0
> > +   },
> > +};
> 
> This looks like a register map to me.
> 
> Can you use the regmap framework instead?

These are platform data used by another driver(thermal driver) which
uses regmap framework to access some of the fields of the structure(
irq_reg, irq_en and evt_stat).


[PATCH v3] gpio: add Intel WhiskeyCove GPIO driver

2016-06-20 Thread Bin Gao
This patch introduces a separate GPIO driver for Intel WhiskeyCove PMIC.
This driver is based on gpio-crystalcove.c.

Signed-off-by: Ajay Thomas 
Signed-off-by: Bin Gao 
---
Changes in v3:
 - Fixed the year in copyright line(2015-->2016).
 - Removed DRV_NAME macro.
 - Added kernel-doc for regmap_irq_chip of the wcove_gpio structure.
 - Line length fix.
Changes in v2:
 - Typo fix (Whsikey --> Whiskey).
 - Included linux/gpio/driver.h instead of linux/gpio.h
 - Implemented .set_single_ended().
 - Added GPIO register description.
 - Replaced container_of() with gpiochip_get_data().
 - Removed unnecessary "if (gpio > WCOVE_VGPIO_NUM" check.
 - Removed the device id table and added MODULE_ALIAS().
 drivers/gpio/Kconfig  |  13 ++
 drivers/gpio/Makefile |   1 +
 drivers/gpio/gpio-wcove.c | 425 ++
 3 files changed, 439 insertions(+)
 create mode 100644 drivers/gpio/gpio-wcove.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index cebcb40..ac74299 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -806,6 +806,19 @@ config GPIO_CRYSTAL_COVE
  This driver can also be built as a module. If so, the module will be
  called gpio-crystalcove.
 
+config GPIO_WHISKEY_COVE
+   tristate "GPIO support for Whiskey Cove PMIC"
+   depends on INTEL_SOC_PMIC
+   select GPIOLIB_IRQCHIP
+   help
+ Support for GPIO pins on Whiskey Cove PMIC.
+
+ Say Yes if you have a Intel SoC based tablet with Whiskey Cove PMIC
+ inside.
+
+ This driver can also be built as a module. If so, the module will be
+ called gpio-wcove.
+
 config GPIO_CS5535
tristate "AMD CS5535/CS5536 GPIO support"
depends on MFD_CS5535
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 991598e..fff6914 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_GPIO_BT8XX)  += gpio-bt8xx.o
 obj-$(CONFIG_GPIO_CLPS711X)+= gpio-clps711x.o
 obj-$(CONFIG_GPIO_CS5535)  += gpio-cs5535.o
 obj-$(CONFIG_GPIO_CRYSTAL_COVE)+= gpio-crystalcove.o
+obj-$(CONFIG_GPIO_WHISKEY_COVE)+= gpio-wcove.o
 obj-$(CONFIG_GPIO_DA9052)  += gpio-da9052.o
 obj-$(CONFIG_GPIO_DA9055)  += gpio-da9055.o
 obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o
diff --git a/drivers/gpio/gpio-wcove.c b/drivers/gpio/gpio-wcove.c
new file mode 100644
index 000..61f6d77
--- /dev/null
+++ b/drivers/gpio/gpio-wcove.c
@@ -0,0 +1,425 @@
+/*
+ * gpio-wcove.c - Intel Whiskey Cove GPIO Driver
+ *
+ * This driver is written based on gpio-crystalcove.c
+ *
+ * Copyright (C) 2016 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * Whiskey Cove PMIC has 13 physical GPIO pins divided into 3 banks:
+ * Bank 0: Pin 0 - 6
+ * Bank 1: Pin 7 - 10
+ * Bank 2: Pin 11 -12
+ * Each pin has one output control register and one input control register.
+ */
+#define BANK0_NR_PINS  7
+#define BANK1_NR_PINS  4
+#define BANK2_NR_PINS  2
+#define WCOVE_GPIO_NUM (BANK0_NR_PINS + BANK1_NR_PINS + BANK2_NR_PINS)
+#define WCOVE_VGPIO_NUM94
+/* GPIO output control registers(one per pin): 0x4e44 - 0x4e50 */
+#define GPIO_OUT_CTRL_BASE 0x4e44
+/* GPIO input control registers(one per pin): 0x4e51 - 0x4e5d */
+#define GPIO_IN_CTRL_BASE  0x4e51
+
+/*
+ * GPIO interrupts are organized in two groups:
+ * Group 0: Bank 0 pins (Pin 0 - 6)
+ * Group 1: Bank 1 and Bank 2 pins (Pin 7 - 12)
+ * Each group has two registers(one bit per pin): status and mask.
+ */
+#define GROUP0_NR_IRQS 7
+#define GROUP1_NR_IRQS 6
+#define IRQ_MASK_BASE  0x4e19
+#define IRQ_STATUS_BASE0x4e0b
+#define UPDATE_IRQ_TYPEBIT(0)
+#define UPDATE_IRQ_MASKBIT(1)
+
+#define CTLI_INTCNT_DIS(0)
+#define CTLI_INTCNT_NE (1 << 1)
+#define CTLI_INTCNT_PE (2 << 1)
+#define CTLI_INTCNT_BE (3 << 1)
+
+#define CTLO_DIR_IN(0)
+#define CTLO_DIR_OUT   (1 << 5)
+
+#define CTLO_DRV_MASK  (1 << 4)
+#define CTLO_DRV_OD(0)
+#define CTLO_DRV_CMOS  CTLO_DRV_MASK
+
+#define CTLO_DRV_REN   (1 << 3)
+
+#define CTLO_RVAL_2KDW (0)
+#define CTLO_RVAL_2KUP (1 << 1)
+#define CTLO_RVAL_50KDW(2 << 1)
+#define CTLO_RVA

Re: [PATCH v2] mfd: intel_soc_pmic_bxtwc: Add Intel BXT WhiskeyCove PMIC ADC thermal channel-zone mapping

2016-06-20 Thread Bin Gao
On Mon, Jun 20, 2016 at 09:52:00AM +0100, Lee Jones wrote:
> > > > > +static struct trip_config_map str3_trip_config[] = {
> > > > > + {
> > > > > + .irq_reg = BXTWC_THRM2IRQ,
> > > > > + .irq_mask = 0x10,
> > > > > + .irq_en = BXTWC_MTHRM2IRQ,
> > > > > + .irq_en_mask = 0x10,
> > > > > + .evt_stat = BXTWC_STHRM2IRQ,
> > > > > + .evt_mask = 0x10,
> > > > > + .trip_num = 0
> > > > > + },
> > > > > +};
> > > > 
> > > > This looks like a register map to me.
> > > > 
> > > > Can you use the regmap framework instead?
> > > 
> > > These are platform data used by another driver(thermal driver) which
> > > uses regmap framework to access some of the fields of the structure(
> > > irq_reg, irq_en and evt_stat).
> > 
> > I suggest you create the regmap here and pass it to the thermal driver
> > instead.
> 
> Better yet, why don't you just create the regmap in the thermal
> driver?  There is no need (in fact, it's not even allowed) to pass
> register addresses though platform data.

We did implement regmap in the acpi opregion driver(see drivers/acpi/pmic
for details) for the PMIC device. Each individual driver, e.g. gpio,
thermal, etc. will only access registers that belong to its logic unit.
Since the shared regmap implementation is already there, a single individual
driver doesn't need to implement again.


Re: x86/tsc: Set X86_FEATURE_TSC_RELIABLE to skip refined calibration

2016-06-20 Thread Bin Gao
On Mon, Jun 20, 2016 at 04:20:26PM -0700, John Stultz wrote:
> On Fri, Jun 17, 2016 at 12:48 AM, Thomas Gleixner  wrote:
> > On Thu, 16 Jun 2016, Bin Gao wrote:
> >
> >> Unlike PIT based calibration which counts TSC cycles against another timer,
> >> MSR or CPUID method has no calibration - it simply multiplies the known
> >> frequency of a timer by a ratio. So TSC frequency computed by MSR or CPUID
> >> is the final frequency and doesn't need the refined calibration process.
> >> We used to use set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE) but
> >> it actually doesn't skip refined calibration because the flag is cleared
> >> later in identify_cpu(). A cpu caps flag is not cleared only if it's set
> >> by setup_force_cpu_cap(). This patch sets the flag in tsc_msr.c and
> >> replaces set_cpu_cap() with setup_force_cpu_cap() in other files.
> >
> > I'm not entirely sure that this is correct. At least I want to know John
> > Stultz's opinion on that.
> 
> So, I'm worried my context here is a bit too stale to be of much use.
> Generally, yea, if we can get the TSC freq from the hardware
> registers, that would be ideal, as there's too many cases where the
> hardware we're calibrating off of has problems.
> 
> But I feel like there were some early edge cases where the MSR didn't
> report the right values on some cpus? I may be remembering this wrong,
> as its been a few years.  That's my main concern, if we start skipping
> the calibration completely, but I'd trust the intel folks have a
> better sense of the edge cases here then my poor memory.
> 
> thanks
> -john

A CPU ID is added to the tsc_msr match table only after we(Intel) verified
it on the real silicon so if a CPU supports MSR method the resulting TSC
frequency must be correct and trustable. The edge cases John mentioned might
be caused be a wrong or missing FSB frequency for a specific CPU. But this is
a software bug, not a hardware problem so it can be found and fixed easily.

To completly skip the delayed refined calibration is inspired by an example
happened recently. One of our customers requires the time drift to be less than
1 second in 24 hours on Intel CherryTrail platform. When the refined calibration
is in place the MSR based result is ignored, so the 24 hours time drift is
3.6 seconds compared to 0.6 second when refined calibration is skipped(so MSR
based result is used by the kernel). This result makes me believe we have to
stick to MSR result whenver it's available.


Re: [PATCH v3] gpio: add Intel WhiskeyCove GPIO driver

2016-06-21 Thread Bin Gao
On Tue, Jun 21, 2016 at 02:19:57AM +0300, Andy Shevchenko wrote:
> My comments below.

Thanks for your review.

> > +config GPIO_WHISKEY_COVE
> > +   tristate "GPIO support for Whiskey Cove PMIC"
> > +   depends on INTEL_SOC_PMIC
> > +   select GPIOLIB_IRQCHIP
> > +   help
> > + Support for GPIO pins on Whiskey Cove PMIC.
> > +
> > + Say Yes if you have a Intel SoC based tablet with Whiskey Cove 
> > PMIC
> 
> What if I have not a tablet with WC PMIC inside?

This driver is for the GPIO controller in the WC PMIC. If there is no WC PMIC,
this driver shouldn't be compiled.
You question is more like:
If a device doesn't exist, what will its driver do?

> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> 
> Alphabetical order?

I checked Documentation/CodingStyle but didn't find any alphabetical order
description. Is this newly enforced?

> > +#define GROUP0_NR_IRQS 7
> > +#define GROUP1_NR_IRQS 6
> > +#define IRQ_MASK_BASE  0x4e19
> > +#define IRQ_STATUS_BASE0x4e0b
> 
> Can you define all your bases as a) offsets by value, and b) with
> _OFFSET suffix instead of _BASE, though second one is up to you.

Strictly speaking, it's called "offset base". I'm really not sure
it will be more readable to replace BASE with OFFSET here.

> > +#define CTLI_INTCNT_DIS(0)
> 
> (0 << 1) or...
> 
> > +#define CTLI_INTCNT_NE (1 << 1)
> > +#define CTLI_INTCNT_PE (2 << 1)
> > +#define CTLI_INTCNT_BE (3 << 1)
> 
> ...INTCNT(x)  ((x) << 1)
> ...DIS 0
> ...NE 1
> 
> and so on.
> 
> Same for all similar blocks of constants.

Makes sense.

> 
> > +
> > +#define CTLO_DIR_IN(0)
> > +#define CTLO_DIR_OUT   (1 << 5)
> > +
> > +#define CTLO_DRV_MASK  (1 << 4)
> > +#define CTLO_DRV_OD(0)
> > +#define CTLO_DRV_CMOS  CTLO_DRV_MASK
> > +
> > +#define CTLO_DRV_REN   (1 << 3)
> > +
> > +#define CTLO_RVAL_2KDW (0)
> > +#define CTLO_RVAL_2KUP (1 << 1)
> > +#define CTLO_RVAL_50KDW(2 << 1)
> > +#define CTLO_RVAL_50KUP(3 << 1)
> 
> Wait, are you sure that's is pure gpio and not a full pinctrl (pinconf) + 
> gpio?

No, we don't have pinctrl for this driver. Those bits are just for pure GPIO 
setting.

> > +static inline unsigned int to_reg(int gpio, enum ctrl_register reg_type)
> > +{
> > +   unsigned int reg;
> > +   int bank;
> > +
> > +   if (gpio < BANK0_NR_PINS)
> > +   bank = 0;
> > +   else if (gpio < (BANK0_NR_PINS + BANK1_NR_PINS))
> > +   bank = 1;
> > +   else
> > +   bank = 2;
> 
> It might be better to use a constant struct to iterate through:
> 
> struct gpio_banks {
>  ... bankno;
>  ... start;
>  ... len;
> };
> 
> Though I have no strong opinion here since it will have only 3 records.

As you said, it's only used once in one function, so not worth to do.

> > +static int wcove_gpio_get(struct gpio_chip *chip, unsigned int gpio)
> > +{
> > +   struct wcove_gpio *wg = gpiochip_get_data(chip);
> > +   int ret;
> > +   unsigned int val;
> 
> Reverse xmas tree, please.

Will do.

> > +static void wcove_bus_lock(struct irq_data *data)
> > +{
> > +   struct wcove_gpio *wg = gpiochip_get_data(
> > +   irq_data_get_irq_chip_data(data));
> > +
> > +   mutex_lock(&wg->buslock);
> 
> I suppose you have to add a hint to static analyzer here and below.

I didn't quite get it. You meant to add some comments for these 2 functions?

> 
> > +}
> > +
> > +static void wcove_bus_sync_unlock(struct irq_data *data)
> > +{
> > +   struct wcove_gpio *wg = gpiochip_get_data(
> > +   irq_data_get_irq_chip_data(data));
> 
> One line

Will do.

> > +static struct irq_chip wcove_irqchip = {
> > +   .name   = "Whiskey Cove",
> > +   .irq_mask   = wcove_irq_mask,
> > +   .irq_unmask = wcove_irq_unmask,
> > +   .irq_set_type   = wcove_irq_type,
> > +   .irq_bus_lock   = wcove_bus_lock,
> > +   .irq_bus_sync_unlock= wcove_bus_sync_unlock,
> 
> Is it my mail client or they are not aligned?

I checked my Sent box as well as the source file and they are well aligned.

> > +   int pending, gpio;
> 
> unsigned int gpio;

Will do.

> > +   if (regmap_read(wg->regmap, IRQ_STATUS_BASE, &p0) ||
> 
> Better to use + 0 here.

Make sense, will do.

> 
> > +   regmap_read(wg->regmap, IRQ_STATUS_BASE + 1, &p1)) {
> > +   pr_err("%s(): regmap_read() failed.\n", __func__);
> 
> dev_err();

Will do.

> > +   regmap_write(wg->regmap, IRQ_STATUS_BASE, p0);
> 
> Ditto.

Will do.

> > +static int wcove_gpio_probe(struct platform_device *pdev)
> > +{
> > +   int virq, retval, irq = platform_get_irq(pdev, 0);
> > +   struct wcove_gpio *wg;
> > +   struct device *dev = pdev->dev.parent;
> > +  

Re: [PATCH v2 1/2] usb: typec: Add USB Power Delivery sink port support

2016-07-27 Thread Bin Gao
On Wed, Jul 27, 2016 at 11:21:13AM +0200, Oliver Neukum wrote:
> On Tue, 2016-07-26 at 11:37 -0700, Bin Gao wrote:
> > +#define MAKE_HEADER(port, header, msg, objs) \
> > +do { \
> > +   header->type = msg; \
> > +   header->data_role = PD_DATA_ROLE_UFP; \
> > +   header->revision = port->pd_rev; \
> > +   header->power_role = PD_POWER_ROLE_SINK; \
> > +   header->id = roll_msg_id(port); \
> > +   header->nr_objs = objs; \
> > +   header->extended = PD_MSG_NOT_EXTENDED; \
> > +} while (0)
> > +
> > +static struct pd_sink_port *sink_ports[MAX_NR_SINK_PORTS];
> > +static int nr_ports;
> > +
> > +BLOCKING_NOTIFIER_HEAD(pd_sink_notifier_list);
> > +
> > +static char *state_strings[] = {
> > +   "WAIT_FOR_SOURCE_CAPABILITY",
> > +   "REQUEST_SENT",
> > +   "ACCEPT_RECEIVED",
> > +   "POWER_SUPPLY_READY",
> > +};
> > +
> > +/* Control messages */
> > +static char *cmsg_strings[] = {
> > +   "GOODCRC",  /* 1 */
> > +   "GOTOMIN",  /* 2 */
> > +   "ACCEPT",   /* 3 */
> > +   "REJECT",   /* 4 */
> > +   "PING", /* 5 */
> > +   "PS_RDY",   /* 6 */
> > +   "GET_SRC_CAP",  /* 7 */
> > +   "GET_SINK_CAP", /* 8 */
> > +   "DR_SWAP",  /* 9 */
> > +   "PR_SWAP",  /* 10 */
> > +   "VCONN_SWAP",   /* 11 */
> > +   "WAIT", /* 12 */
> > +   "SOFT_RESET",   /* 13 */
> > +   "RESERVED", /* 14 */
> > +   "RESERVED", /* 15 */
> > +   "NOT_SUPPORTED",/* 16 */
> > +   "GET_SOURCE_CAP_EXTENDED",  /* 17 */
> > +   "GET_STATUS",   /* 18 */
> > +   "FR_SWAP",  /* 19 */
> > +   /* RESERVED 20 - 31 */
> > +};
> > +
> > +/* Data messages */
> > +static char *dmsg_strings[] = {
> > +   "SOURCE_CAP",   /* 1 */
> > +   "REQUEST",  /* 2 */
> > +   "BIST", /* 3 */
> > +   "SINK_CAP", /* 4 */
> > +   "BATTERY_STATUS",   /* 5 */
> > +   "ALERT",/* 6 */
> > +   "RESERVED", /* 7 */
> > +   "RESERVED", /* 8 */
> > +   "RESERVED", /* 9 */
> > +   "RESERVED", /* 10 */
> > +   "RESERVED", /* 11 */
> > +   "RESERVED", /* 12 */
> > +   "RESERVED", /* 13 */
> > +   "RESERVED", /* 14 */
> > +   "VENDOR_DEFINED",   /* 15 */
> > +   /* RESERVED 16 - 31 */
> > +};
> > +
> > +static char *state_to_string(enum pd_sink_state state)
> > +{
> > +   if (state < ARRAY_SIZE(state_strings))
> > +   return state_strings[state];
> > +   else
> > +   return NULL;
> > +}
> > +
> > +static char *msg_to_string(bool is_cmsg, u8 msg)
> > +{
> > +   int nr = is_cmsg ? ARRAY_SIZE(cmsg_strings) :
> > ARRAY_SIZE(dmsg_strings);
> > +
> > +   if (msg <= nr)
> > +   return is_cmsg ? cmsg_strings[msg - 1] :
> > dmsg_strings[msg - 1];
> > +   else
> > +   return "RESERVED";
> > +}
> > +
> > +static void print_message(int port, bool is_cmsg, u8 msg, bool recv)
> > +{
> > +   pr_debug("sink port %d: %s message %s %s\n", port,
> > +   is_cmsg ? "Control" : "Data",
> > +   msg_to_string(is_cmsg, msg),
> > +recv ? "received" : "sent)");
> > +}
> > +
> > +static inline bool fixed_ps_equal(struct sink_ps *p1,
> > +   struct sink_ps *p2)
> > +{
> > +   return p1->ps_type == p2->ps_type &&
> > +   p1->ps_fixed.voltage_fixed ==
> > p2->ps_fixed.voltage_fixed &&
> > +   p1->ps_fixed.current_default ==
> > p2->ps_fixed.current_default;
> > +}
> > +
> > +/* The message ID increments each time we send out a new message */
> > +static u8 roll_msg_id(struct pd_sink_port *port)
> > +{
> > +   u8 msg_id = port->msg_id;
> > +
> > +   if (msg_id == PD_MSG_ID_MAX)
> > +   msg_id = PD_MSG_ID_MIN;
> > +   else
> > +   msg_id++;
> > +
> > +   port->msg_id = msg_id;
> > +   return msg_id;
> > +}
> > +
> 
> These pieces of code are completely generic. They should be shared
> among drivers. Please move them into the include files.
> 
>   Regards
>   Oliver
> 
> 

They are only internally used by this driver (USB PD state machine driver).
And they are not used by drivers (typicall USB Type-C phy drivers) which
use APIs exposed by this driver. So I think it's not appropriate to move
to include files.


Re: [PATCH v2 1/2] usb: typec: Add USB Power Delivery sink port support

2016-07-27 Thread Bin Gao
On Wed, Jul 27, 2016 at 11:13:43AM +0300, Felipe Balbi wrote:
> 
> Hi,
> 
> Bin Gao  writes:
> > This patch implements a simple USB Power Delivery sink port state machine.
> > It assumes the hardware only handles PD packet transmitting and receiving
> > over the CC line of the USB Type-C connector. The state transition is
> > completely controlled by software. This patch only implement the sink port
> > function and it doesn't support source port and port swap yet.
> >
> > This patch depends on these two patches:
> > https://lkml.org/lkml/2016/6/29/349
> > https://lkml.org/lkml/2016/6/29/350
> >
> > Signed-off-by: Bin Gao 
> > Changes in v2:
> >  - Removed work queue so messages are directly handled in phy driver's 
> > interrupt context
> >  - used pr_debug instead of pr_info for message dump
> >  - Converted PD driver to tristate and typec driver is independent of it
> 
> this should be after the tearline (---) below. We don't want this in
> changelog ;-)
> 
> > +static void handle_source_cap(struct pd_sink_port *port, u8 msg_revision,
> > +   u8 nr_objs, u8 *buf)
> > +{
> > +   int i;
> > +   u32 *obj;
> > +   u8 type;
> > +   struct pd_source_cap *cap = port->source_caps;
> > +
> > +   /*
> > +* The PD spec revision included in SOURCE_CAPABILITY message is the
> > +* highest revision that the Source supports.
> > +*/
> > +   port->pd_rev = msg_revision;
> > +
> > +   /*
> > +* First we need to save all PDOs - they may be used in the future.
> > +* USB PD spec says we must use PDOs in the most recent
> > +* SOURCE_CAPABILITY message. Here we replace old PDOs with new ones.
> > +*/
> > +   port->nr_source_caps = 0;
> > +   for (i = 0; i < nr_objs; i++) {
> > +   obj = (u32 *)(buf + i * PD_OBJ_SIZE);
> > +   type = (*obj >> SOURCE_CAP_TYPE_BIT) & SOURCE_CAP_TYPE_MASK;
> > +   switch (type) {
> > +   case PS_TYPE_FIXED:
> > +   cap->ps_type = PS_TYPE_FIXED;
> > +   cap->fixed = *(struct pd_pdo_src_fixed *)obj;
> > +   break;
> > +   case PS_TYPE_VARIABLE:
> > +   cap->ps_type = PS_TYPE_VARIABLE;
> > +   cap->variable = *(struct pd_pdo_variable *)obj;
> > +   break;
> > +   case PS_TYPE_BATTERY:
> > +   cap->ps_type = PS_TYPE_BATTERY;
> > +   cap->battery = *(struct pd_pdo_battery *)obj;
> > +   break;
> > +   default: /* shouldn't come here */
> > +   pr_err("Invalid Source Capability type: %u.\n", type);
> > +   continue;
> > +   }
> > +   port->nr_source_caps++;
> > +   cap++;
> > +   }
> > +
> > +   if (port->nr_source_caps == 0) {
> > +   pr_err("There is no valid PDOs in SOURCE_CAPABILITY message\n");
> > +   return;
> > +   }
> > +
> > +   /* If a contract is not established, we need send a REQUEST message */
> > +   if (port->state == PD_SINK_STATE_WAIT_FOR_SRC_CAP) {
> 
> this is wrong. Read the fluxchart in figure 8-42. Source can decide to
> send another Source Capability before receiving our Good CRC and we need
> to work with that. This state check is, at a minimum, wrong. I'd
> actually just go ahead and remove it.
> 
> > +   if (!send_request(port))
> > +   port->state = PD_SINK_STATE_REQUEST_SENT;
> > +   }
> > +}
> 
> -- 
> balbi

I'll fix these in next revision. Thanks for your review.

-Bin


Re: [PATCH v2] x86/tsc: Set X86_FEATURE_TSC_RELIABLE to skip refined calibration

2016-08-25 Thread Bin Gao
On Wed, Aug 24, 2016 at 10:51:20AM +0200, Thomas Gleixner wrote:
> On Tue, 16 Aug 2016, Bin Gao wrote:
> > On some newer Intel x86 processors/SoCs the TSC frequency can be directly
> > calculated by factors read from specific MSR registers or from a cpuid
> > leaf (0x15). TSC frequency calculated by native msr/cpuid is absolutely
> > accurate so we should always skip calibrating TSC aginst another clock,
> > e.g. PIT, HPET, etc. So we want to skip the refined calibration by setting
> > the X86_FEATURE_TSC_RELIABLE flag. Existing code setting the flag by
> > set_cpu_cap() doesn't work as the flag is cleared later in identify_cpu().
> > A cpu caps flag is not cleared only if it's set by setup_force_cpu_cap().
> > This patch converted set_cpu_cap() to setup_force_cpu_cap() to ensure
> > refined calibration is skipped.
> > 
> > We had a test on Intel CherryTrail platform: the 24 hours time drift is
> > 3.6 seconds if refined calibration was not skipped while the drift is less
> > than 0.6 second when refined calibration was skipped.
> > 
> > Correctly setting the X86_FEATURE_TSC_RELIABLE flag also guarantees TSC is
> > not monitored by timekeeping watchdog because on most of these system TSC
> > is the only reliable clocksource. HPET, for instance, works but may not
> > be reliable. So kernel may report a physically reliable TSC is not reliable
> > just because a physically not reliable HPET is acting as timekeeping
> > watchdog.
> 
> What about non SoC systems where the MSR is available, but we still see that
> cross socket TSC wreckage? This change will prevent the watchdog from
> detecting that.

MSR is only available on Intel Atom SoCs. There is no such a multi-socket 
system.

> 
> Thanks,
> 
>   tglx


Re: [PATCH v4 1/2] serial_core: add pci uart early console support

2015-05-27 Thread Bin Gao
Peter Hurley,
First of all, thank you for your reviewing.
Please see my answers below.

On Tue, May 26, 2015 at 01:12:34PM -0400, Peter Hurley wrote:
> Hi Bin,
> 
> Please don't drop lists (or other addressees) from patch revisions.
> 
> [ +cc linux-serial]
Will fix this.


> Please update Documentation/kernel-parameters.txt with pci-specific
> earlycon parameter formats.
Will do.

 
> Please move this hunk to patch 2/2.
It's already in 2/2. Or I'm not quite understanding?


> FYI, there is a proposal to evaluate "earlyprintk=" earlier than
> parse_early_params(), which this would break.
> 
> https://lkml.org/lkml/2015/5/18/127
No, it wouldn't. The proposal only moves earlyprintk=serial(legacy 0x3f8).
If you look into arch/x86/kernel/early_printk.c, you'll find many other
options other than serial, e.g. vga, dbgp, xen, efi, pciserial, etc.
uart8250(previously pciserial) is one of these "others".


> > +static int parse_bdf(char *options, char **endp, char delimiter, u8 *val)
> 
> If this function is only used from parse_pci_options(), please enclose it
> in #ifdef CONFIG_PCI_EARLY scope with parse_pci_options().
Yes, will fix it.


> 
> > +{
> > +   char str[4]; /* max 3 chars, plus a NULL terminator */
> > +   char *p = options;
> > +   int i = 0;
> > +
> > +   while (*p) {
> > +   if (i >= 4)
> > +   return -EINVAL;
> > +
> > +   if (*p == delimiter) {
> > +   str[i++] = 0;
> > +   if (endp)
> > +   *endp = p + 1;
> > +   return kstrtou8(str, 10, val); /* decimal, no hex */
> > +   }
> > +
> > +   str[i++] = *p++;
> > +   }
> 
> Is all this to avoid using simple_strtoul()?
> If yes, I'd rather you use simple_strtoul() like the rest of the console
> code and ignore the (misguided) advice that simple_strtoul() is obsolete.
Then scripts/checkpatch.pl should be updated to avoid this kind of "misguiding".
Also the kstrto* API descriptions should be updated...


> The code above is exactly what is wrong with the kstrto* api.
Can you elaborate a little bit? Thanks.


> > +   if (!early_pci_allowed()) {
> > +   pr_err("earlycon pci not available(early pci not allowed)\n");
> 
> Error message is redundant.
"early pci not allowed" is the reason of "earlycon pci not available".


> > +   /*
> > +* On these platforms class code in pci config is broken,
>   ^^^
> which platforms?
On platforms where this code will run on.
Do you prefer something like:
On platforms with early pci serial class code in pci config is broken,


> > +   pr_info("Use 8250 uart at PCI :%02u:%02u.%01u as early console\n",
> > +   bus, dev, func);
> 
> I think one earlycon banner is sufficient; you could make this pr_debug()
> instead. Existing convention for earlycon messages is
> 
>   "earlycon: "
Will use pr_debug().


> >   * @options: ptr for  field; NULL if not present (out)
> >   *
> >   * Decodes earlycon kernel command line parameters of the form
> > - *earlycon=,io|mmio|mmio32,,
> > + *earlycon=,io|mmio|mmio32|pci|pci32,,
> 
> Document the pci/pci32 format separately because
>   earlycon=uart8250,pci32,, is not a valid form.
Why it's not a valid form? It follows the existed syntax like this:
earlycon=uart8250,,,


> > @@ -1829,12 +1939,23 @@ uart_get_console(struct uart_port *ports, int nr, 
> > struct console *co)
> >  int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long 
> > *addr,
> > char **options)
> >  {
> > +   int pci = 0, ret;
> > +   unsigned long phys;
> > +
> > if (strncmp(p, "mmio,", 5) == 0) {
> > *iotype = UPIO_MEM;
> > p += 5;
> > } else if (strncmp(p, "mmio32,", 7) == 0) {
> > *iotype = UPIO_MEM32;
> > p += 7;
> > +   } else if (strncmp(p, "pci,", 4) == 0) {
> > +   pci = 1;
> > +   p += 4;
> > +   ret = parse_pci_options(p, &phys);
> > +   } else if (strncmp(p, "pci32,", 6) == 0) {
> > +   pci = 2;
> > +   p += 6;
> > +   ret = parse_pci_options(p, &phys);
> > } else if (strncmp(p, "io,", 3) == 0) {
> > *iotype = UPIO_PORT;
> > p += 3;
> > @@ -1844,7 +1965,27 @@ int uart_parse_earlycon(char *p, unsigned char 
> > *iotype, unsigned long *addr,
> > return -EINVAL;
> > }
> >  
> > -   *addr = simple_strtoul(p, NULL, 0);
> > +   if (pci) {
> > +   if (ret < 0) /* error */
> > +   return ret;
> > +
> > +   /*
> > +* Once PCI mem/io is read from PCI BAR, we can reuse
> > +* mmio/mmio32/io type to minimize code change.
> > +*/
> > +   if (ret > 0) /* PCI io */
> > +   *iotype = UPIO_PORT;
> > +   else { /* ret = 0: PCI mem */
> > +   if (pci == 2)
> > +   *iotype = UPIO_MEM32;
> > 

Re: [PATCH v4 1/2] serial_core: add pci uart early console support

2015-05-27 Thread Bin Gao
On Sun, May 24, 2015 at 12:52:25PM -0700, Greg Kroah-Hartman wrote:
> > Signed-off-by: Bin Gao 
> > ---
> > Changes in v4:
> >  - moved PCI_EARLY definition from arch/x86/Kconfig to drivers/pci/Kconfig
> >  - added 'earlyprintk' for x86 as alias to the early param 'earlycon'
> 
> What about the changes in earlier versions?
> 
> And why do I have 3 copies of different "v4" patches in my inbox?
> 
> Please resend this, as v5, correctly, and we can review it that way.
> 
> greg k-h

Will address this altogether with comments from other reviewers in v5. Thanks.

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


Re: [PATCH v4 1/2] serial_core: add pci uart early console support

2015-05-28 Thread Bin Gao
On Wed, May 27, 2015 at 08:21:21PM -0400, Peter Hurley wrote:
> I meant that the patch hunk below should be moved to patch
> 2/2, and the purpose of patch 2/2 should be to replace x86-specific
> earlyprintk=pciserial with arch-independent earlyprintk=pciserial.
> 
> There are 2 reasons for my suggestion:
> 1) Changes to x86 earlyprintk should get acks from the x86 maintainers.
>Borislav Petkov  is particularly involved in the
>'early' earlyprintk proposal. Patch 2/2 should cc them and the
>author of the original earlyprintk=pciserial patch.
> 2) Changes to x86 earlyprintk may be rejected.
> 
> 
> > +/* x86 uses "earlyprintk=xxx", so we keep the compatibility here */
> > +#ifdef CONFIG_X86
> > +static int __init param_setup_earlycon_x86(char *buf)
> > +{
> > +   return param_setup_earlycon(buf);
> > +}
> > +early_param("earlyprintk", param_setup_earlycon_x86);
> > +#endif
> > +
Ok now I got it.


> >> FYI, there is a proposal to evaluate "earlyprintk=" earlier than
> >> parse_early_params(), which this would break.
> >>
> >> https://lkml.org/lkml/2015/5/18/127
> > No, it wouldn't. The proposal only moves earlyprintk=serial(legacy 0x3f8).
> > If you look into arch/x86/kernel/early_printk.c, you'll find many other
> > options other than serial, e.g. vga, dbgp, xen, efi, pciserial, etc.
> > uart8250(previously pciserial) is one of these "others".
> 
> I see; so when re-evaluating earlyprintk= for earlycon, there is no danger 
> of corrupting the device state for earlyprintk?
No, because uart8250 is a unknown value to earlyprintk= in
arch/x86/kernel/early_prink.c, so it simply returns from there.
 
> However, the namespace will now be shared so that is an important change
> that maintainers and future earlycon/earlyprintk authors need to know.
Yes, I'll cc more x86 people.

 
> > Then scripts/checkpatch.pl should be updated to avoid this kind of 
> > "misguiding".
> > Also the kstrto* API descriptions should be updated...
> 
> I know; I've already made that point to Joe.
> 
> >> The code above is exactly what is wrong with the kstrto* api.
> > Can you elaborate a little bit? Thanks.
> 
> I don't mean there is anything wrong with _your_ code, per se.
> Rather that it should not be necessary to write 14 lines of code, use temp
> storage and visit the entire string three times simply to parse a string
> into a number. IOW, the kstrto* API usefulness is limited, which is why
> simple_strto* is _not_ obsolete.
> 
>  
> >>> + if (!early_pci_allowed()) {
> >>> + pr_err("earlycon pci not available(early pci not allowed)\n");
> >>
> >> Error message is redundant.
> > "early pci not allowed" is the reason of "earlycon pci not available".
> 
> Only one or the other is necessary. For example,
> 
>   "earlycon: early pci not allowed\n"
Will do.


> 
> 
> >>> + /*
> >>> +  * On these platforms class code in pci config is broken,
> >>   ^^^
> >> which platforms?
> > On platforms where this code will run on.
> > Do you prefer something like:
> > On platforms with early pci serial class code in pci config is broken,
> 
> This statement doesn't make sense to me: the original earlyprintk=pciserial
> implementation read the class code register, so it worked then.
> 
> Why not now?
Indeed on real silicon the class code is broken.
I would say it might be an accident that those class code related codes
were checked in...


> >>>   *   @options: ptr for  field; NULL if not present (out)
> >>>   *
> >>>   *   Decodes earlycon kernel command line parameters of the form
> >>> - *  earlycon=,io|mmio|mmio32,,
> >>> + *  earlycon=,io|mmio|mmio32|pci|pci32,,
> >>
> >> Document the pci/pci32 format separately because
> >>earlycon=uart8250,pci32,, is not a valid form.
> > Why it's not a valid form? It follows the existed syntax like this:
> > earlycon=uart8250,,,
> 
> Well, isn't  being retrieved from BAR0? Why would you specify
> the  on the command line?
> 
> But I see now that's where the 'bus:device.function' goes.
> I think if I was confused, others will be too. Further, in the context
> of this code 'addr' is a variable to which the command line parameter
> comment identifies, whereas 'bus:device.function' does not follow
> the same convention.
I think it's confusing because pci is special - we can say B:D.F is PCI
address(bus address), but address from BAR is also pci address(IO or
Memory address). How about we undertand the  from the comment
is bus address? So for mmio, it's 32bit(or 64bit) physical address, for
pci it's B:D.F.

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


[PATCH v6 1/2] serial_core: add pci uart early console support

2015-06-08 Thread Bin Gao
On some Intel Atom SoCs, the legacy IO port UART(0x3F8) is not available.
Instead, a 8250 compatible PCI uart can be used as early console.
This patch adds pci support to the 8250 early console driver uart8250.
For example, to enable pci uart(00:21.3) as early console on these
platforms, append the following line to the kernel command line
(assume baud rate is 115200):
earlyprintk=uart8250,pci32,0:24.2,115200n8

Signed-off-by: Bin Gao 
---
Changes in v6: None
Changes in v5:
 - updated Documentation/kernel-parameters.txt.
 - moved earlyprintk= to patch 2/2 (requires x86 people's review).
 - rolled back to simple_strto* APIs.
 - seperate pci/pci32 format description.
 - minor error and debug message changes.
 - if/else statements in uart_parse_earlycon() were refactored to avoid
   logic steering locals.
Changes in v4:
 - moved PCI_EARLY definition from arch/x86/Kconfig to drivers/pci/Kconfig
 - made earlycon= for all archs but earlyprintk= only for x86 by changing
   "#ifdef #else #endif" to "#if #endif".
Changes in v3:
 - introduced CONFIG_EARLY_PCI to protect pci codes in serial_core.c.
 - added earlyprintk= as alia to earlycon= to keep x86 compatibility.
changes in v2:
 - added the second patch (2/2) to remove existed pci early console support
   from arch/x86/kernel/early_printk.c.
 Documentation/kernel-parameters.txt |  15 +
 arch/x86/Kconfig|   1 +
 drivers/pci/Kconfig |  11 
 drivers/tty/serial/serial_core.c| 106 +++-
 4 files changed, 132 insertions(+), 1 deletion(-)

diff --git a/Documentation/kernel-parameters.txt 
b/Documentation/kernel-parameters.txt
index 61ab162..598606e 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -969,6 +969,16 @@ bytes respectively. Such letter suffixes can also be 
entirely omitted.
same format described for "console=ttyS"; if
unspecified, the h/w is not initialized.
 
+   uart8250,pci,[,options]
+   uart8250,pci32,[,options]
+   Start an early, polled-mode console on the 8250/16550
+   UART at the specified PCI device (bus:dev.func).
+   The io or memory mmaped register width is either 8-bit
+   (pci) or 32-bit (pci32).
+   'options' are specified in the same format described
+   for "console=ttyS"; if unspecified, the h/w is not
+   initialized.
+
pl011,
Start an early, polled-mode console on a pl011 serial
port at the specified address. The pl011 serial port
@@ -1009,6 +1019,8 @@ bytes respectively. Such letter suffixes can also be 
entirely omitted.
earlyprintk=serial[,0x...[,baudrate]]
earlyprintk=ttySn[,baudrate]
earlyprintk=dbgp[debugController#]
+   earlyprintk=uart8250,pci,[,options]
+   earlyprintk=uart8250,pci32,[,options]
 
earlyprintk is useful when the kernel crashes before
the normal console is initialized. It is not enabled by
@@ -1037,6 +1049,9 @@ bytes respectively. Such letter suffixes can also be 
entirely omitted.
 
The xen output can only be used by Xen PV guests.
 
+   The uart8250,pci and uart8250,pci32 output share the
+   same definition that is in earlycon= section.
+
edac_report=[HW,EDAC] Control how to report EDAC event
Format: {"on" | "off" | "force"}
on: enable EDAC to report H/W event. May be overridden
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 226d569..bdedd61 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -143,6 +143,7 @@ config X86
select ACPI_LEGACY_TABLES_LOOKUP if ACPI
select X86_FEATURE_NAMES if PROC_FS
select SRCU
+   select PCI_EARLY if PCI
 
 config INSTRUCTION_DECODER
def_bool y
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 7a8f1c5..4f0f055 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -114,4 +114,15 @@ config PCI_LABEL
def_bool y if (DMI || ACPI)
select NLS
 
+config PCI_EARLY
+   bool "Early PCI access"
+   depends on PCI
+   default n
+   help
+ This option indicates that a group of APIs are available (in
+ asm/pci-direct.h) so the kernel can access pci config registers
+ before the PCI subsystem is initialized. Any arch that supports
+ early pci APIs should enable this option which is required  by
+ arch independent codes, e.g. uart8250 pci early console driver.
+
 source "drivers/pci/host/Kco

[PATCH v6 2/2] arch/x86: remove pci uart early console from early_prink.c

2015-06-08 Thread Bin Gao
The arch independent uart8250 early console driver has good
support for memory mapped and io port based 8250 uarts. Since
pci is arch independent so it's natural to extend uart8250 to
support mem, io and pci. Hence pci uart early console in
arch/x86/kernel_printk.c by the following commit:
'commit 5140fda16051 ("Specify PCI based UART for earlyprintk")'
is removed. And its equivalent function will be available from
uart8250 early console driver.

Signed-off-by: Bin Gao 
---
Changes in v6:
 - limited the early parameter 'earlyprintk' in drivers/tty/serial/earlycon.c
   to uart8250,pci[32][,options] only
Changes in v5:
 - moved earlyprintk= (an alias to earlycon=) from patch 1/2 to patch 2/2
Changes in v2-v4: None
 arch/x86/kernel/early_printk.c | 180 -
 drivers/tty/serial/earlycon.c  |  15 
 2 files changed, 30 insertions(+), 165 deletions(-)

diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index 89427d8..00c2e2a 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -19,7 +19,6 @@
 #include 
 #include 
 #include 
-#include 
 
 /* Simple VGA output */
 #define VGABASE(__ISA_IO_base + 0xb8000)
@@ -77,7 +76,7 @@ static struct console early_vga_console = {
 
 /* Serial functions loosely based on a similar package from Klaus P. Gerlicher 
*/
 
-static unsigned long early_serial_base = 0x3f8;  /* ttyS0 */
+static int early_serial_base = 0x3f8;  /* ttyS0 */
 
 #define XMTRDY  0x20
 
@@ -95,26 +94,13 @@ static unsigned long early_serial_base = 0x3f8;  /* ttyS0 */
 #define DLL 0   /*  Divisor Latch Low */
 #define DLH 1   /*  Divisor latch High*/
 
-static unsigned int io_serial_in(unsigned long addr, int offset)
-{
-   return inb(addr + offset);
-}
-
-static void io_serial_out(unsigned long addr, int offset, int value)
-{
-   outb(value, addr + offset);
-}
-
-static unsigned int (*serial_in)(unsigned long addr, int offset) = 
io_serial_in;
-static void (*serial_out)(unsigned long addr, int offset, int value) = 
io_serial_out;
-
 static int early_serial_putc(unsigned char ch)
 {
unsigned timeout = 0x;
 
-   while ((serial_in(early_serial_base, LSR) & XMTRDY) == 0 && --timeout)
+   while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
cpu_relax();
-   serial_out(early_serial_base, TXR, ch);
+   outb(ch, early_serial_base + TXR);
return timeout ? 0 : -1;
 }
 
@@ -128,28 +114,13 @@ static void early_serial_write(struct console *con, const 
char *s, unsigned n)
}
 }
 
-static __init void early_serial_hw_init(unsigned divisor)
-{
-   unsigned char c;
-
-   serial_out(early_serial_base, LCR, 0x3);/* 8n1 */
-   serial_out(early_serial_base, IER, 0);  /* no interrupt */
-   serial_out(early_serial_base, FCR, 0);  /* no fifo */
-   serial_out(early_serial_base, MCR, 0x3);/* DTR + RTS */
-
-   c = serial_in(early_serial_base, LCR);
-   serial_out(early_serial_base, LCR, c | DLAB);
-   serial_out(early_serial_base, DLL, divisor & 0xff);
-   serial_out(early_serial_base, DLH, (divisor >> 8) & 0xff);
-   serial_out(early_serial_base, LCR, c & ~DLAB);
-}
-
 #define DEFAULT_BAUD 9600
 
 static __init void early_serial_init(char *s)
 {
+   unsigned char c;
unsigned divisor;
-   unsigned long baud = DEFAULT_BAUD;
+   unsigned baud = DEFAULT_BAUD;
char *e;
 
if (*s == ',')
@@ -174,138 +145,23 @@ static __init void early_serial_init(char *s)
s++;
}
 
-   if (*s) {
-   if (kstrtoul(s, 0, &baud) < 0 || baud == 0)
-   baud = DEFAULT_BAUD;
-   }
-
-   /* Convert from baud to divisor value */
-   divisor = 115200 / baud;
-
-   /* These will always be IO based ports */
-   serial_in = io_serial_in;
-   serial_out = io_serial_out;
-
-   /* Set up the HW */
-   early_serial_hw_init(divisor);
-}
-
-#ifdef CONFIG_PCI
-static void mem32_serial_out(unsigned long addr, int offset, int value)
-{
-   u32 *vaddr = (u32 *)addr;
-   /* shift implied by pointer type */
-   writel(value, vaddr + offset);
-}
-
-static unsigned int mem32_serial_in(unsigned long addr, int offset)
-{
-   u32 *vaddr = (u32 *)addr;
-   /* shift implied by pointer type */
-   return readl(vaddr + offset);
-}
-
-/*
- * early_pci_serial_init()
- *
- * This function is invoked when the early_printk param starts with "pciserial"
- * The rest of the param should be ",B:D.F,baud" where B, D & F describe the
- * location of a PCI device that must be a UART device.
- */
-static __init void early_pci_serial_init(char *s)
-{
-   unsigned divisor;
-   unsigned long baud = DEFAULT_BAUD;
-   u8 bu

Re: [PATCH v5 2/2] arch/x86: remove pci uart early console from early_prink.c

2015-06-02 Thread Bin Gao
On Tue, Jun 02, 2015 at 01:54:33PM +0200, Ingo Molnar wrote:
> 
> * Bin Gao  wrote:
> 
> > The arch independent uart8250 early console driver has good support for 
> > memory 
> > mapped and io port based 8250 uarts. Since pci is arch independent so it's 
> > natural to extend uart8250 to support mem, io and pci. Hence pci uart early 
> > console in arch/x86/kernel_printk.c by the following commit: 'commit 
> > 5140fda16051 ("Specify PCI based UART for earlyprintk")' is removed. And 
> > its 
> > equivalent function will be available from uart8250 early console driver.
> 
> In what way have you tested this change, does serial-earlyprintk still work 
> on x86 
> after the change?
> 
> Thanks,
> 
>   Ingo

Yes, this patch was tested with earlyprintk=serial,0x3f8 on my x86 box and
the early console worked fine.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 2/2] arch/x86: remove pci uart early console from early_prink.c

2015-06-02 Thread Bin Gao
On Tue, Jun 02, 2015 at 11:46:02PM +0200, Ingo Molnar wrote:
> So the format on x86 used to be:
> 
>   earlyprintk=serial,ttyS0,115200
> 
> does that work too?
> 
> Thanks,
> 
>   Ingo
Just tested it, and yes it works.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 2/2] arch/x86: remove pci uart early console from early_prink.c

2015-06-02 Thread Bin Gao
On Tue, Jun 02, 2015 at 11:07:39PM +0200, Thomas Gleixner wrote:
> What about the memory mapped uarts which have been source of trouble
> in the past?
> 
> Thanks,
> 
>   tglx

Not sure which specific early console you are referring to.
Currently we have serial, ttyS, vga, dbgp, xen, efi and pciserial in
arch/x86/kernel/early_printk.c, and only pciserial is memory mapped
(but it's being removed).

And this patch only touches pciserial/serial parts so ideally shouldn't
have impact on other early consoles.

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


Re: [PATCH v5 2/2] arch/x86: remove pci uart early console from early_prink.c

2015-06-02 Thread Bin Gao
On Tue, Jun 02, 2015 at 01:37:52PM -0700, Yinghai Lu wrote:
> how about
> earlyprintk=serial,ttyS0
> earlyprintk=ttyS0
> 
> Thanks
> 
> Yinghai

Yes, both work.

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


Re: [PATCH v5 2/2] arch/x86: remove pci uart early console from early_prink.c

2015-06-02 Thread Bin Gao
On Wed, Jun 03, 2015 at 12:16:36AM +, Anderson, Stuart R wrote:
> Bin, et al,
> 
> What we are losing here is the ability to specify a UART by its bus address
> instead of just supplying the memory or io address. There are some cases
> where this is useful, though I admit it is probably not going to be widely
> used. I have seen a platform where the location of the UART moves depending
> on the firmware version, but the bus address (B:D.F) did not change. There
> are also some platforms where you do not know the address until you boot the
> OS and can use the UART to login and find the address of the UART (oops.
> Chicken and egg problem).
> 
> Also, I was going to soon send a patch to allow "pciserial32" for the case 
> where the UART registers are 32-bit aligned instead of 8-bit aligned.
> 
> Stuart
> 

Theare are several reasons that we want to move it to serial_core.
First, pci is arch independent, so putting these codes in serial_core
(which is arch independent) makes more sense.
Second, B:D.F may change across SoCs, then to support new SoC we only
need change command line but don't need to change the code.
Lastly, there could be other non-x86 platforms using it in the future.

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


Re: [PATCH v5 2/2] arch/x86: remove pci uart early console from early_prink.c

2015-06-03 Thread Bin Gao
On Wed, Jun 03, 2015 at 08:35:29AM -0400, Peter Hurley wrote:
> > +/* x86 uses "earlyprintk=xxx", so we keep the compatibility here */
> > +#ifdef CONFIG_X86
> > +static int __init param_setup_earlycon_x86(char *buf)
> > +{
> > +   return param_setup_earlycon(buf);
> > +}
> > +early_param("earlyprintk", param_setup_earlycon_x86);
> 
> I'm concerned that this effectively makes earlyprintk= a synonym for
> earlycon=, which may have unforeseen consequences. I'd rather this
> specifically parse for replacement functionality, ie., only command line
> parameters of the form:
> 
>   earlyprintk=pciserial,...
> 
> Regards,
> Peter Hurley
> 

Something like this: ?

/*
 * x86 uses "earlyprintk=xxx", so we keep the compatibility here.
 * But we only handle the earlyprintk=uart8250,pci[32]B:D.F[,options] case.
 */
#ifdef CONFIG_X86
static int __init param_setup_earlycon_x86(char *buf)
{
if (strncmp("uart8250,pci", 12))
return -EINVAL;
 
return param_setup_earlycon(buf);
}
early_param("earlyprintk", param_setup_earlycon_x86);

Thanks,
Bin

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


[PATCH v5 1/2] serial_core: add pci uart early console support

2015-05-29 Thread Bin Gao
On some Intel Atom SoCs, the legacy IO port UART(0x3F8) is not available.
Instead, a 8250 compatible PCI uart can be used as early console.
This patch adds pci support to the 8250 early console driver uart8250.
For example, to enable pci uart(00:21.3) as early console on these
platforms, append the following line to the kernel command line
(assume baud rate is 115200):
earlyprintk=uart8250,pci32,0:24.2,115200n8

Signed-off-by: Bin Gao 
---
Changes in v5:
 - updated Documentation/kernel-parameters.txt.
 - moved earlyprintk= to patch 2/2 (requires x86 people's review).
 - rolled back to simple_strto* APIs.
 - seperate pci/pci32 format description.
 - minor error and debug message changes.
 - if/else statements in uart_parse_earlycon() were refactored to avoid
   logic steering locals.
Changes in v4:
 - moved PCI_EARLY definition from arch/x86/Kconfig to drivers/pci/Kconfig
 - made earlycon= for all archs but earlyprintk= only for x86 by changing
   "#ifdef #else #endif" to "#if #endif".
Changes in v3:
 - introduced CONFIG_EARLY_PCI to protect pci codes in serial_core.c.
 - added earlyprintk= as alia to earlycon= to keep x86 compatibility.
changes in v2:
 - added the second patch (2/2) to remove existed pci early console support
   from arch/x86/kernel/early_printk.c.
 Documentation/kernel-parameters.txt |  15 +
 arch/x86/Kconfig|   1 +
 drivers/pci/Kconfig |  11 
 drivers/tty/serial/serial_core.c| 106 +++-
 4 files changed, 132 insertions(+), 1 deletion(-)

diff --git a/Documentation/kernel-parameters.txt 
b/Documentation/kernel-parameters.txt
index 61ab162..598606e 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -969,6 +969,16 @@ bytes respectively. Such letter suffixes can also be 
entirely omitted.
same format described for "console=ttyS"; if
unspecified, the h/w is not initialized.
 
+   uart8250,pci,[,options]
+   uart8250,pci32,[,options]
+   Start an early, polled-mode console on the 8250/16550
+   UART at the specified PCI device (bus:dev.func).
+   The io or memory mmaped register width is either 8-bit
+   (pci) or 32-bit (pci32).
+   'options' are specified in the same format described
+   for "console=ttyS"; if unspecified, the h/w is not
+   initialized.
+
pl011,
Start an early, polled-mode console on a pl011 serial
port at the specified address. The pl011 serial port
@@ -1009,6 +1019,8 @@ bytes respectively. Such letter suffixes can also be 
entirely omitted.
earlyprintk=serial[,0x...[,baudrate]]
earlyprintk=ttySn[,baudrate]
earlyprintk=dbgp[debugController#]
+   earlyprintk=uart8250,pci,[,options]
+   earlyprintk=uart8250,pci32,[,options]
 
earlyprintk is useful when the kernel crashes before
the normal console is initialized. It is not enabled by
@@ -1037,6 +1049,9 @@ bytes respectively. Such letter suffixes can also be 
entirely omitted.
 
The xen output can only be used by Xen PV guests.
 
+   The uart8250,pci and uart8250,pci32 output share the
+   same definition that is in earlycon= section.
+
edac_report=[HW,EDAC] Control how to report EDAC event
Format: {"on" | "off" | "force"}
on: enable EDAC to report H/W event. May be overridden
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 226d569..bdedd61 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -143,6 +143,7 @@ config X86
select ACPI_LEGACY_TABLES_LOOKUP if ACPI
select X86_FEATURE_NAMES if PROC_FS
select SRCU
+   select PCI_EARLY if PCI
 
 config INSTRUCTION_DECODER
def_bool y
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 7a8f1c5..4f0f055 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -114,4 +114,15 @@ config PCI_LABEL
def_bool y if (DMI || ACPI)
select NLS
 
+config PCI_EARLY
+   bool "Early PCI access"
+   depends on PCI
+   default n
+   help
+ This option indicates that a group of APIs are available (in
+ asm/pci-direct.h) so the kernel can access pci config registers
+ before the PCI subsystem is initialized. Any arch that supports
+ early pci APIs should enable this option which is required  by
+ arch independent codes, e.g. uart8250 pci early console driver.
+
 source "drivers/pci/host/Kconfig"
diff 

[PATCH v5 2/2] arch/x86: remove pci uart early console from early_prink.c

2015-05-29 Thread Bin Gao
The arch independent uart8250 early console driver has good
support for memory mapped and io port based 8250 uarts. Since
pci is arch independent so it's natural to extend uart8250 to
support mem, io and pci. Hence pci uart early console in
arch/x86/kernel_printk.c by the following commit:
'commit 5140fda16051 ("Specify PCI based UART for earlyprintk")'
is removed. And its equivalent function will be available from
uart8250 early console driver.

Signed-off-by: Bin Gao 
---
Changes in v5:
 - moved earlyprintk= (an alias to earlycon=) from patch 1/2 to patch 2/2
Changes in v2-v4:
 - no changes but keep going with patch 1/2
 arch/x86/kernel/early_printk.c | 180 -
 drivers/tty/serial/earlycon.c  |   9 +++
 2 files changed, 24 insertions(+), 165 deletions(-)

diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index 89427d8..00c2e2a 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -19,7 +19,6 @@
 #include 
 #include 
 #include 
-#include 
 
 /* Simple VGA output */
 #define VGABASE(__ISA_IO_base + 0xb8000)
@@ -77,7 +76,7 @@ static struct console early_vga_console = {
 
 /* Serial functions loosely based on a similar package from Klaus P. Gerlicher 
*/
 
-static unsigned long early_serial_base = 0x3f8;  /* ttyS0 */
+static int early_serial_base = 0x3f8;  /* ttyS0 */
 
 #define XMTRDY  0x20
 
@@ -95,26 +94,13 @@ static unsigned long early_serial_base = 0x3f8;  /* ttyS0 */
 #define DLL 0   /*  Divisor Latch Low */
 #define DLH 1   /*  Divisor latch High*/
 
-static unsigned int io_serial_in(unsigned long addr, int offset)
-{
-   return inb(addr + offset);
-}
-
-static void io_serial_out(unsigned long addr, int offset, int value)
-{
-   outb(value, addr + offset);
-}
-
-static unsigned int (*serial_in)(unsigned long addr, int offset) = 
io_serial_in;
-static void (*serial_out)(unsigned long addr, int offset, int value) = 
io_serial_out;
-
 static int early_serial_putc(unsigned char ch)
 {
unsigned timeout = 0x;
 
-   while ((serial_in(early_serial_base, LSR) & XMTRDY) == 0 && --timeout)
+   while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
cpu_relax();
-   serial_out(early_serial_base, TXR, ch);
+   outb(ch, early_serial_base + TXR);
return timeout ? 0 : -1;
 }
 
@@ -128,28 +114,13 @@ static void early_serial_write(struct console *con, const 
char *s, unsigned n)
}
 }
 
-static __init void early_serial_hw_init(unsigned divisor)
-{
-   unsigned char c;
-
-   serial_out(early_serial_base, LCR, 0x3);/* 8n1 */
-   serial_out(early_serial_base, IER, 0);  /* no interrupt */
-   serial_out(early_serial_base, FCR, 0);  /* no fifo */
-   serial_out(early_serial_base, MCR, 0x3);/* DTR + RTS */
-
-   c = serial_in(early_serial_base, LCR);
-   serial_out(early_serial_base, LCR, c | DLAB);
-   serial_out(early_serial_base, DLL, divisor & 0xff);
-   serial_out(early_serial_base, DLH, (divisor >> 8) & 0xff);
-   serial_out(early_serial_base, LCR, c & ~DLAB);
-}
-
 #define DEFAULT_BAUD 9600
 
 static __init void early_serial_init(char *s)
 {
+   unsigned char c;
unsigned divisor;
-   unsigned long baud = DEFAULT_BAUD;
+   unsigned baud = DEFAULT_BAUD;
char *e;
 
if (*s == ',')
@@ -174,138 +145,23 @@ static __init void early_serial_init(char *s)
s++;
}
 
-   if (*s) {
-   if (kstrtoul(s, 0, &baud) < 0 || baud == 0)
-   baud = DEFAULT_BAUD;
-   }
-
-   /* Convert from baud to divisor value */
-   divisor = 115200 / baud;
-
-   /* These will always be IO based ports */
-   serial_in = io_serial_in;
-   serial_out = io_serial_out;
-
-   /* Set up the HW */
-   early_serial_hw_init(divisor);
-}
-
-#ifdef CONFIG_PCI
-static void mem32_serial_out(unsigned long addr, int offset, int value)
-{
-   u32 *vaddr = (u32 *)addr;
-   /* shift implied by pointer type */
-   writel(value, vaddr + offset);
-}
-
-static unsigned int mem32_serial_in(unsigned long addr, int offset)
-{
-   u32 *vaddr = (u32 *)addr;
-   /* shift implied by pointer type */
-   return readl(vaddr + offset);
-}
-
-/*
- * early_pci_serial_init()
- *
- * This function is invoked when the early_printk param starts with "pciserial"
- * The rest of the param should be ",B:D.F,baud" where B, D & F describe the
- * location of a PCI device that must be a UART device.
- */
-static __init void early_pci_serial_init(char *s)
-{
-   unsigned divisor;
-   unsigned long baud = DEFAULT_BAUD;
-   u8 bus, slot, func;
-   u32 classcode, bar0;
-   u16 cmdreg;
-   char *e;
-
-
-   /*
-

Re: [PATCH v2] x86, tsc: Add missing Baytrail frequency to the table

2014-01-25 Thread Bin Gao
> diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index a3acbac2ee72$
> --- a/arch/x86/kernel/tsc.c
> +++ b/arch/x86/kernel/tsc.c
> @@ -655,10 +655,11 @@ unsigned long native_calibrate_tsc(void)
>   local_irq_save(flags);
>   i = try_msr_calibrate_tsc(&fast_calibrate);
>   local_irq_restore(flags);
> - if (i >= 0) {
> - if (i == 0)
> - pr_warn("Fast TSC calibration using MSR failed\n");
> + if (i > 0) {
>   return fast_calibrate;
> + } else if (i == 0) {
> + pr_warn("Fast TSC calibration using MSR failed\n");
> + /* Continue with the normal calibration */
>   }
>
>   local_irq_save(flags);

The original design is to avoid trying PIC because touching PIC on
a non-PIC SoC will simply cause system hang. Returning 0 will cause
kernel to mark TSC unstable(rating 0). Since PM timer and HPET are
typically not available on non-PIC SoC, kernal falls back to jiffies
as clock source. Developers will start looking into the TSC clibrating
failure once they notice the jiffies clock source.

>[] clockevents_config_and_register+0x20/0x30
>[] setup_APIC_timer+0xc8/0xd0
>[] setup_boot_APIC_clock+0x4cc/0x4d8
>[] native_smp_prepare_cpus+0x3dd/0x3f0
>[] kernel_init_freeable+0xc3/0x205
>[] ? rest_init+0x90/0x90
>[] kernel_init+0xe/0x120
>[] ret_from_fork+0x7c/0xb0
>[] ? rest_init+0x90/0x90

This is because kernel is trying to use tsc-deadline mode for lapic
timer. I think the right fix is to unset X86_FEATURE_TSC_DEADLINE_TIMER
when try_msr_calibrate_tsc() returns 0.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2] x86, tsc: Add missing Baytrail frequency to the table

2014-01-29 Thread Bin Gao
On Tue, Jan 28, 2014 at 02:04:07PM +0200, Mika Westerberg wrote:
> Actually it does not work. I had the fallback path still in the patch when
> I tried.

Let's merge the ptach v2 then(continue on msr calibration retuning 0).
All supported SoCs now have the correct frequency ID coding
so continuing on non-PIC SoCs has very very small possibility.

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


[PATCH 1/4] drivers/misc: add rawio framework driver

2013-10-21 Thread Bin Gao
Rawio provides a framework to read/write registers from a bus, including
pci, i2c, I/O device(memory mapped), etc. based on debug fs.
Rawio bus drivers implement the read/write operation on a specific bus
on top of the rawio framework driver.
They are designed to help device driver and kernel debugging on
embedded systems.

Signed-off-by: Bin Gao 
---
 drivers/misc/Kconfig|   1 +
 drivers/misc/Makefile   |   1 +
 drivers/misc/rawio/Kconfig  |  21 ++
 drivers/misc/rawio/Makefile |   1 +
 drivers/misc/rawio/rawio.c  | 514

 include/linux/rawio.h   |  78 +++
 6 files changed, 616 insertions(+)
 create mode 100644 drivers/misc/rawio/Kconfig
 create mode 100644 drivers/misc/rawio/Makefile
 create mode 100644 drivers/misc/rawio/rawio.c
 create mode 100644 include/linux/rawio.h

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 8dacd4c..1afbe4e 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -537,4 +537,5 @@ source "drivers/misc/carma/Kconfig"
 source "drivers/misc/altera-stapl/Kconfig"
 source "drivers/misc/mei/Kconfig"
 source "drivers/misc/vmw_vmci/Kconfig"
+source "drivers/misc/rawio/Kconfig"
 endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index c235d5b..3bc116b 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -53,3 +53,4 @@ obj-$(CONFIG_INTEL_MEI)   += mei/
 obj-$(CONFIG_VMWARE_VMCI)  += vmw_vmci/
 obj-$(CONFIG_LATTICE_ECP3_CONFIG)  += lattice-ecp3-config.o
 obj-$(CONFIG_SRAM) += sram.o
+obj-$(CONFIG_RAWIO)+= rawio/
diff --git a/drivers/misc/rawio/Kconfig b/drivers/misc/rawio/Kconfig
new file mode 100644
index 000..fd4272e
--- /dev/null
+++ b/drivers/misc/rawio/Kconfig
@@ -0,0 +1,21 @@
+#
+# rawio utility drivers
+#
+
+menuconfig RAWIO
+   tristate "Debug fs based raw io device read/write framework "
+   depends on DEBUG_FS
+   default no
+   help
+ This option enables support for reading or writing registers/memory
+ region in a io device via debug fs.
+ With this option and related rawio driver options enabled, you could
+ read configuration space of a PCI device, registers of a memory
+ mapped or port mapped device, registers of a i2c device, etc.
+ This is the just the framework driver. You need enable more
+ options to support specific device types.
+
+ To compile this driver as a module, choose M: the module will
+ be called rawio.
+
+ If you are not sure, say N here.
diff --git a/drivers/misc/rawio/Makefile b/drivers/misc/rawio/Makefile
new file mode 100644
index 000..c21453c
--- /dev/null
+++ b/drivers/misc/rawio/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_RAWIO)+= rawio.o
diff --git a/drivers/misc/rawio/rawio.c b/drivers/misc/rawio/rawio.c
new file mode 100644
index 000..a05b493
--- /dev/null
+++ b/drivers/misc/rawio/rawio.c
@@ -0,0 +1,514 @@
+/*
+ * rawio.c - a debugfs based framework for reading/writing registers
+ * from a I/O device.
+ * With pluggable rawio drivers, it can support PCI devices, I2C devices,
+ * memory mapped I/O devices, etc.
+ * It's designed for helping debug Linux device drivers on embedded
system or
+ * SoC platforms.
+ *
+ * Copyright (c) 2013 Bin Gao 
+ *
+ * This file is released under the GPLv2
+ *
+ *
+ * Two files are created in debugfs root folder: rawio_cmd and
rawio_output.
+ * To read or write via the rawio debugfs interface, first echo a rawio
+ * command to the file rawio_cmd, then cat the file rawio_output:
+ * $ echo "" > /sys/kernel/debug/rawio_cmd
+ * $ cat /sys/kernel/debug/rawio_output
+ * The cat command is required for both read and write operations.
+ * For details of rawio command format, see specific rawio drivers.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define SHOW_NUM_PER_LINE  (32 / active_width)
+#define LINE_WIDTH 32
+#define IS_WHITESPACE(c)   ((c) == ' ' || (c) == '\t' || (c) == '\n')
+
+static struct dentry *rawio_cmd_dentry, *rawio_output_dentry;
+static char rawio_cmd_buf[RAWIO_CMD_LEN], rawio_err_buf[RAWIO_ERR_LEN + 1];
+static DEFINE_MUTEX(rawio_lock);
+static LIST_HEAD(rawio_driver_head);
+static struct rawio_driver *active_driver;
+static enum width active_width;
+static enum ops active_ops;
+static u64 args_val[RAWIO_ARGS_MAX];
+static u8 args_postfix[RAWIO_ARGS_MAX];
+static int num_args_val;
+
+static void store_value(u64 *where, void *value, enum type type)
+{
+   switch (type) {
+   case TYPE_U8:
+   *(u8 *)where = *(u8 *)value;
+   break;
+   case TYPE_U16:
+   *(u16 *)where = *(u16 *)value;
+   break;
+   case TYPE_U32:
+   *(u32 *

[PATCH 2/4] drivers/misc: add rawio pci driver

2013-10-21 Thread Bin Gao
With pci rawio driver, you can read/write any pci config space register
by debug fs interface. This driver is based on the rawio framework.

Signed-off-by: Bin Gao 
---
 drivers/misc/rawio/Kconfig |  15 +++
 drivers/misc/rawio/Makefile|   1 +
 drivers/misc/rawio/rawio_pci.c | 235
+
 3 files changed, 251 insertions(+)
 create mode 100644 drivers/misc/rawio/rawio_pci.c

diff --git a/drivers/misc/rawio/Kconfig b/drivers/misc/rawio/Kconfig
index fd4272e..47be40a 100644
--- a/drivers/misc/rawio/Kconfig
+++ b/drivers/misc/rawio/Kconfig
@@ -19,3 +19,18 @@ menuconfig RAWIO
  be called rawio.

  If you are not sure, say N here.
+
+if RAWIO
+
+config RAWIO_PCI
+   tristate "rawio PCI driver"
+   depends on RAWIO && PCI
+   default no
+   help
+ This option enables the rawio PCI driver.
+ With this driver, you can read or write any PCI device's
+ configuration space via debugfs.
+ To compile this driver as a module, choose M: the module will
+ be called rawio_pci.
+
+endif # RAWIO
diff --git a/drivers/misc/rawio/Makefile b/drivers/misc/rawio/Makefile
index c21453c..0933ca6 100644
--- a/drivers/misc/rawio/Makefile
+++ b/drivers/misc/rawio/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_RAWIO)+= rawio.o
+obj-$(CONFIG_RAWIO_PCI)+= rawio_pci.o
diff --git a/drivers/misc/rawio/rawio_pci.c b/drivers/misc/rawio/rawio_pci.c
new file mode 100644
index 000..052ad1b
--- /dev/null
+++ b/drivers/misc/rawio/rawio_pci.c
@@ -0,0 +1,235 @@
+/*
+ * rawio_pci.c - a driver to read/write pci configuration space
registers based
+ *   on the rawio framework.
+ *
+ * 1: byte, 2: word, 4: dword
+ *
+ * read pci config space registers
+ * echo "r[1|2|4] pci  []" >
+ * /sys/kernel/debug/rawio_cmd
+ * cat /sys/kernel/debug/rawio_output
+ * e.g. echo "r1 pci 0 0 3 0 8 12" > /sys/kernel/debug/rawio_cmd
+ *  cat /sys/kernel/debug/rawio_output
+ *
+ * write a pci config space register:
+ * echo "w[1|2|4] pci  " >
+ * /sys/kernel/debug/rawio_output
+ * cat /sys/kernel/debug/rawio_output
+ * e.g. echo "w pci 0 0 0x11 2 0x10 0x" >
/sys/kernel/debug/rawio_cmd
+ *      cat /sys/kernel/debug/rawio_output
+ *
+ *
+ * Copyright (c) 2013 Bin Gao 
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int pci_prepare(int pci_domain, unsigned int pci_bus,
+   u8 pci_dev, u8 pci_func, enum width width,
+   u16 pci_reg, u16 len, struct pci_dev **ppdev)
+{
+   struct pci_dev *pdev;
+   int ret;
+
+   if (((width == WIDTH_2) && (pci_reg & 0x1)) ||
+   ((width == WIDTH_4) && (pci_reg & 0x3))) {
+   rawio_err("register address requires 2 bytes aligned for 16 bit
access, and 4 bytes aligned for 32 bit access\n");
+   return -EINVAL;
+   }
+
+   pdev = pci_get_domain_bus_and_slot(pci_domain, pci_bus,
+   PCI_DEVFN(pci_dev, pci_func));
+   if (!pdev) {
+   rawio_err("pci device %04x:%02x:%02x.%01x doesn't exist\n",
+   pci_domain, pci_bus, pci_dev, pci_func);
+   return -ENODEV;
+   }
+
+   if (((pci_reg >= 0x100) && !pci_is_pcie(pdev)) ||
+   (pci_reg >= 0x1000)) {
+   rawio_err("register address is out of range\n");
+   return -EINVAL;
+   }
+
+   if pci_reg + len * width) >= 0x100) && !pci_is_pcie(pdev)) ||
+   ((pci_reg + len * width) >= 0x1000)) {
+   rawio_err("register address is out of range\n");
+   return -EINVAL;
+   }
+
+   ret = pm_runtime_get_sync(&pdev->dev);
+   if ((ret >= 0) || (ret == -EACCES))
+   goto out;
+
+   rawio_err("can't put pci device %04x:%02x:%02x.%01xinto running state,
pm_runtime_get_sync() returned %d\n",
+   pci_domain, pci_bus, pci_dev, pci_func, ret);
+   return -EBUSY;
+
+out:
+   *ppdev = pdev;
+   return 0;
+}
+
+static void pci_finish(struct pci_dev *pdev)
+{
+   pm_runtime_put_sync(&pdev->dev);
+}
+
+static int rawio_pci_read(struct rawio_driver *driver, int width,
+   u64 *input, u8 *postfix, int input_num,
+   void **output, int *output_num)
+{
+   int i, ret, pci_domain;
+   struct pci_dev *pdev;
+   unsigned int pci_bus;
+   u8 pci_dev, pci_func;
+   u16 pci_reg, len;
+   void *buf;
+
+   pci_domain = (int)input[0];
+   pci_bus = (unsigned int)input[1];
+   pci_dev = (u8)i

[PATCH 0/4] drivers/misc: add rawio framework and drivers

2013-10-21 Thread Bin Gao
To read/write registers from a device is very important on embedded system,
especially SoC systems. Physically there could be different types of devices
based on bus tyes, e.g. PCI devices, I2C (slave)devices, I/O devices(memory
mapped), inter-processor devices, etc. Typically there are userland
tools from
PC Linux to access device registers, but on some embedded system initrd and
rootfs come with a minimal busybox and most useful userland tools are not
available. To add these tools back to rootfs is not convenient either.
What's more, on some systems with runtime pm enabled, reading/writing
registers
from a device which is in low power state will cause problems. For these
reasons, to have some tools/interfaces directly from kernel space via debug
fs seems to be easy, cheap and convenient.

These patchsets are designed to  achieve above goals to ease
device driver and kernel debugging on embedded systems.

Rawio provides a framework to read/write registers from a bus, including
pci, i2c, I/O device(memory mapped), etc. based on debug fs.
Rawio bus drivers implement the read/write operation on a specific bus
on top of the rawio framework driver.
Currently only three bus drivers are available: pci, iomem and i2c.
But it's extremely easy to add more drivers on top of the framework
if needed.

 drivers/misc/Kconfig |   1 +
 drivers/misc/Makefile|   1 +
 drivers/misc/rawio/Kconfig   |  59 +
 drivers/misc/rawio/Makefile  |   4 +
 drivers/misc/rawio/rawio.c   | 514
+++
 drivers/misc/rawio/rawio_i2c.c   | 224 +
 drivers/misc/rawio/rawio_iomem.c | 401 ++
 drivers/misc/rawio/rawio_pci.c   | 235 ++
 include/linux/rawio.h|  78 ++
 9 files changed, 1517 insertions(+)
 create mode 100644 drivers/misc/rawio/Kconfig
 create mode 100644 drivers/misc/rawio/Makefile
 create mode 100644 drivers/misc/rawio/rawio.c
 create mode 100644 drivers/misc/rawio/rawio_i2c.c
 create mode 100644 drivers/misc/rawio/rawio_iomem.c
 create mode 100644 drivers/misc/rawio/rawio_pci.c
 create mode 100644 include/linux/rawio.h
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 4/4] drivers/misc: add rawio i2c driver

2013-10-21 Thread Bin Gao
With i2c rawio driver, you can read/write registers from any i2c
client(slave) device via debug fs interface.
This driver is based on the rawio framework.

Signed-off-by: Bin Gao 
---
 drivers/misc/rawio/Kconfig |  11 ++
 drivers/misc/rawio/Makefile|   1 +
 drivers/misc/rawio/rawio_i2c.c | 224
+
 3 files changed, 236 insertions(+)
 create mode 100644 drivers/misc/rawio/rawio_i2c.c

diff --git a/drivers/misc/rawio/Kconfig b/drivers/misc/rawio/Kconfig
index 38e8a52..9ffbc5d 100644
--- a/drivers/misc/rawio/Kconfig
+++ b/drivers/misc/rawio/Kconfig
@@ -45,4 +45,15 @@ config RAWIO_IOMEM
  To compile this driver as a module, choose M: the module will
  be called rawio_iomem.

+config RAWIO_I2C
+   tristate "rawio I2C driver"
+   depends on RAWIO && I2C
+   default no
+   help
+ This option enables the rawio I2C driver.
+ With this driver, you can read or write any I2C device's
+ register debugfs interface.
+ To compile this driver as a module, choose M: the module will
+ be called rawio_i2c.
+
 endif # RAWIO
diff --git a/drivers/misc/rawio/Makefile b/drivers/misc/rawio/Makefile
index 5f86257..9e33aec 100644
--- a/drivers/misc/rawio/Makefile
+++ b/drivers/misc/rawio/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_RAWIO)+= rawio.o
 obj-$(CONFIG_RAWIO_PCI)+= rawio_pci.o
 obj-$(CONFIG_RAWIO_IOMEM)  += rawio_iomem.o
+obj-$(CONFIG_RAWIO_I2C)+= rawio_i2c.o
diff --git a/drivers/misc/rawio/rawio_i2c.c b/drivers/misc/rawio/rawio_i2c.c
new file mode 100644
index 000..f872602
--- /dev/null
+++ b/drivers/misc/rawio/rawio_i2c.c
@@ -0,0 +1,224 @@
+/*
+ * rawio_i2c.c - rawio I2C driver.
+ * Read or write a I2C device's register, based on the rawio framework.
+ *
+ * Copyright (c) 2013 Bin Gao 
+ *
+ * This file is released under the GPLv2
+ *
+ *
+ * read i2c registers:
+ * echo "r i2c[]" >
+ * /sys/kernel/debug/rawio_cmd
+ * cat /sys/kernel/debug/rawio_output
+ * e.g. echo "r i2c 3 0x6b 0x84 5" > /sys/kernel/debug/rawio_cmd
+ *  cat /sys/kernel/debug/rawio_output
+ *
+ * write a i2c register:
+ * echo "w i2c" >
+ * /sys/kernel/debug/rawio_cmd
+ * cat /sys/kernel/debug/rawio_output
+ * e.g. echo "w i2c 4 0x70 0x4 0xfa" > /sys/kernel/debug/rawio_cmd
+ *  cat /sys/kernel/debug/rawio_output
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int i2c_prepare(u8 i2c_bus, u16 i2c_addr, u16 i2c_reg, u16 len,
+   int ten_bit_addr, struct i2c_adapter **ppadap)
+{
+   struct i2c_adapter *adap;
+
+   adap = i2c_get_adapter((int)i2c_bus);
+   if (!adap) {
+   rawio_err("can't find bus adapter for i2c bus %d\n",
+   i2c_bus);
+   return -ENODEV;
+   }
+
+   if ((!ten_bit_addr && (i2c_addr > 128)) || (i2c_addr > 1024)) {
+   rawio_err("register address is out of range, forgot 't' for 
10bit
addr?\n");
+   return -EINVAL;
+   }
+
+   if ((!ten_bit_addr && ((i2c_addr + len) > 128)) ||
+   ((i2c_addr + len) > 1024)) {
+   rawio_err("register address is out of range, forgot 't' for 
10bit
addr?\n");
+   return -EINVAL;
+   }
+
+   *ppadap = adap;
+   return 0;
+}
+
+static int rawio_i2c_read(struct rawio_driver *driver, int width, u64
*input,
+   u8 *postfix, int input_num, void **output, int *output_num)
+{
+   int ret, len;
+   struct i2c_adapter *adap;
+   u16 i2c_addr, i2c_reg;
+   struct i2c_msg msg[2];
+   u8 i2c_bus, buf[2], *out_buf, ten_bit_addr, sixteen_bit_reg;
+
+   i2c_bus = (u8)input[0];
+   i2c_addr = (u16)input[1];
+   i2c_reg = (u16)input[2];
+
+   len = 1;
+   if (input_num == 4)
+   len = (u16)input[3];
+
+   ten_bit_addr = postfix[1];
+   sixteen_bit_reg = postfix[2];
+
+   ret = i2c_prepare(i2c_bus, i2c_addr, i2c_reg, len, ten_bit_addr, &adap);
+   if (ret)
+   return ret;
+
+   out_buf = kzalloc(sizeof(u8) * len, GFP_KERNEL);
+   if (buf == NULL) {
+   rawio_err("can't alloc memory\n");
+   return -ENOMEM;
+   }
+   buf[0] = i2c_reg & 0xff;
+   buf[1] = (i2c_reg >> 8) & 0xff;
+
+   /* write i2c reg address */
+   msg[0].addr = i2c_addr;
+   msg[0].flags = ten_bit_addr ? I2C_M_TEN : 0;
+   msg[0].len = sixteen_bit_reg ? 2 : 1;
+   msg[0].buf = buf;
+
+   /* read i2c reg */
+   msg[1].addr = i2c_addr;
+   msg[1].flags = I2C_M_RD | (ten_bit_addr ? I2C_M_TEN : 0);
+   msg[1].len = len;
+   msg[1].buf = out_buf;

[PATCH 3/4] drivers/misc: add rawio iomem driver

2013-10-21 Thread Bin Gao
With iomem rawio driver, you can read/write memory mapped registers
from any I/O device via debug fs interface.
This driver is based on the rawio framework.

Signed-off-by: Bin Gao 
---
 drivers/misc/rawio/Kconfig   |  12 ++
 drivers/misc/rawio/Makefile  |   1 +
 drivers/misc/rawio/rawio_iomem.c | 401
+++
 3 files changed, 414 insertions(+)
 create mode 100644 drivers/misc/rawio/rawio_iomem.c

diff --git a/drivers/misc/rawio/Kconfig b/drivers/misc/rawio/Kconfig
index 47be40a..38e8a52 100644
--- a/drivers/misc/rawio/Kconfig
+++ b/drivers/misc/rawio/Kconfig
@@ -33,4 +33,16 @@ config RAWIO_PCI
  To compile this driver as a module, choose M: the module will
  be called rawio_pci.

+config RAWIO_IOMEM
+   tristate "rawio I/O memory driver"
+   depends on RAWIO
+   default no
+   help
+ This option enables the rawio I/O memory driver.
+ With this driver, you can read or write registers of a memory
+ mapped I/O devices.
+
+ To compile this driver as a module, choose M: the module will
+ be called rawio_iomem.
+
 endif # RAWIO
diff --git a/drivers/misc/rawio/Makefile b/drivers/misc/rawio/Makefile
index 0933ca6..5f86257 100644
--- a/drivers/misc/rawio/Makefile
+++ b/drivers/misc/rawio/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_RAWIO)+= rawio.o
 obj-$(CONFIG_RAWIO_PCI)+= rawio_pci.o
+obj-$(CONFIG_RAWIO_IOMEM)  += rawio_iomem.o
diff --git a/drivers/misc/rawio/rawio_iomem.c
b/drivers/misc/rawio/rawio_iomem.c
new file mode 100644
index 000..eaae773
--- /dev/null
+++ b/drivers/misc/rawio/rawio_iomem.c
@@ -0,0 +1,401 @@
+/*
+ * rawio_iomem.c - a driver to read or write a device's I/O memory,
based on
+ * the rawio debugfs framework.
+ *
+ * Copyright (c) 2013 Bin Gao 
+ *
+ * This file is released under the GPLv2
+ *
+ *
+ * 1: byte, 2: word, 4: dword
+ *
+ * I/O mem read:
+ * echo "r[1|2|4] iomem  []" >
/sys/kernel/debug/rawio_cmd
+ * cat /sys/kernel/debug/rawio_output
+ * e.g. echo "r iomem 0xff003040 20" > /sys/kernel/debug/rawio_cmd
+ *  cat /sys/kernel/debug/rawio_output
+ *
+ * I/O mem write:
+ * echo "w[1|2|4] iomem  " >
/sys/kernel/debug/rawio_cmd
+ * cat /sys/kernel/debug/rawio_output
+ * e.g. echo "w2 iomem 0xff003042 0xb03f" > /sys/kernel/debug/rawio_cmd
+ *  cat /sys/kernel/debug/rawio_output
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * On some platforms, a read or write to a device which is in a low power
+ * state will cause a system error, or even cause a system reboot.
+ * To address this, we use runtime PM APIs to bring up the device to
+ * runnint state before use and put back to original state after use.
+ *
+ * We could use lookup_resource() to map an physical address to a device,
+ * but there are some problems:
+ * 1) lookup_resource() is not exported, so a kernel module can't use it;
+ * 2) To use the 'name' field of 'struct resource' to match a device is
+ *not reliable;
+ * So we rather walk known device types than look up the resrouce list
+ * to map a physical address(I/O memory address) to a device.
+ */
+
+/* return true if range(start: m2, size: n2) is in range(start: m1,
size: n1) */
+#define IN_RANGE(m1, n1, m2, n2) \
+   (((m2 >= m1) && (m2 < (m1 + n1))) && \
+   (((m2 + n2) >= m1) && ((m2 + n2) < (m1 + n1
+
+struct dev_walker {
+   resource_size_t addr;
+   resource_size_t size;
+   struct device *dev;
+   int error;
+};
+
+#ifdef CONFIG_PCI
+int walk_pci_devices(struct device *dev, void *data)
+{
+   int i;
+   resource_size_t start, len;
+   struct pci_dev *pdev = (struct pci_dev *) to_pci_dev(dev);
+   struct dev_walker *walker = (struct dev_walker *) data;
+
+   if (!pdev)
+   return -ENODEV;
+
+   walker->dev = NULL;
+   for (i = 0; i < 6; i++) {
+   start = pci_resource_start(pdev, i);
+   len = pci_resource_len(pdev, i);
+   if (IN_RANGE(start, len, walker->addr, walker->size)) {
+   walker->dev = dev;
+   return 1;
+   }
+   }
+
+   return 0;
+}
+#endif
+
+int walk_platform_devices(struct device *dev, void *data)
+{
+   int i;
+   struct resource *r;
+   resource_size_t start, len;
+   struct platform_device *plat_dev = to_platform_device(dev);
+   struct dev_walker *walker = (struct dev_walker *) data;
+
+   walker->dev = NULL;
+   for (i = 0; i < plat_dev->num_resources; i++) {
+   r = platform_get_resource(plat_dev, IORESOURCE_MEM, i);
+   if (!r)
+   continue;
+   start = r->star

Re: [PATCH 0/4] drivers/misc: add rawio framework and drivers

2013-10-22 Thread Bin Gao
On Tue, Oct 22, 2013 at 06:44:06AM +0100, Greg Kroah-Hartman wrote:
> So, just because userspace is "hard" you want to add stuff to the kernel
> instead.
> 
Well, there are other reasons - "hard" is just one of them.
For instance, on some platforms with runtime pm enabled, access to registers
of a device which is in low power state will cause problems(syste reboot, etc.).
You can only wake it up to running state by runtime API from kernel space.

> Sorry, but for over the past decade, we have been doing just the
> opposite, if things can be done in userspace, then they should be done
> there.  So for us to go in the opposite direction, like these patches
> show, would be a major change.
> 
Agree, but as mentioned above, for some situation we can't do it from
user space.

> You can already do this today for PCI with the UIO framework, right?
> Why duplicate that functionality here with another userapce API that we
> will then have to maintain for the next 40+ years?
> 
No, UIO is not appropriate for my requirement.
The thing I need is to dump any registers just by 2 simple commands.

> All of your patches are line-wrapped and totally fail to apply, so even
> if we wanted to take this type of changes, I couldn't :(
> 
Sorry for that. I recently upgraded my email client, will fix it next posting.

> Have you run these proposed changes by any of the Intel kernel
> developers?  What did they say to them?
> 
> If not, why haven't you, isn't that a resource you should be using for
> things like this?
> 
Why you had these strange questions?
Over years, we have been maintaining and using these drivers internally 
for various purpose across our group for SoC pre-silicon and post-silicon
degugging, e.g. IOAPIC RTE dumping, GPIO tunning, raw device degugging
without a driver(i2c, spi, uart), etc., etc., ...
Trying to push some existed codes upstream is not a bad thing.

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


Re: [PATCH 1/4] drivers/misc: add rawio framework driver

2013-10-22 Thread Bin Gao
On Tue, Oct 22, 2013 at 06:45:38AM +0100, Greg Kroah-Hartman wrote:
> 
> Oh, one more technical thing, you totally fail to document the
> user/kernel api you have just created.

Yes, this is required to be done. Will fix it.

> You are parsing userspace data in ways that I really don't understand at 
> all...

I don't know which specific codes you were talking about.
Overall the driver needs to parse each argument from the user command.
For example: "r iomem 0xff00c020 40", the driver needs parsing out:
r   - read (and default width 4 bytes)
iomem   - I/O memory
0xff00c020  - the start address to read
40  - length to read

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


Re: [PATCH 0/4] drivers/misc: add rawio framework and drivers

2013-10-22 Thread Bin Gao
On Tue, Oct 22, 2013 at 10:14:00AM -0700, Guenter Roeck wrote:
> > 
> > You can already do this today for PCI with the UIO framework, right?
> > Why duplicate that functionality here with another userapce API that we
> > will then have to maintain for the next 40+ years?
> > 
> Same for i2c, where the same functionality is supported through i2c-tools and
> the i2c-dev driver. Adding i2c-tools to initramfs and/or to the root file 
> system
> should not be that much of an issue, much less than having to maintain two 
> APIs
> for the same purpose.
> 
> Guenter

For PCI and memory mapped I/O devices, we have the runtime pm issue that has to
be addressed from kernel space.
For I2C slave devices, there is no such a issue so yes i2c-tools and i2c-dev 
drivers
are fine. But the two APIs are required by PCI and memory mapped I/O devices 
anyway.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v6 1/2] serial_core: add pci uart early console support

2015-07-27 Thread Bin Gao
On Thu, Jul 23, 2015 at 03:21:27PM -0700, Greg Kroah-Hartman wrote:
> > +config PCI_EARLY
> > +   bool "Early PCI access"
> > +   depends on PCI
> > +   default n
> 
> Default is always 'n' so this isn't needed here.

Will fix this.

> > diff --git a/drivers/tty/serial/serial_core.c 
> > b/drivers/tty/serial/serial_core.c
> > index 0b7bb12..5b21999 100644
> > --- a/drivers/tty/serial/serial_core.c
> > +++ b/drivers/tty/serial/serial_core.c
> > @@ -34,10 +34,15 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  
> >  #include 
> >  #include 
> >  
> > +#ifdef CONFIG_PCI_EARLY
> > +#include 
> > +#endif
> 
> You shouldn't need an #ifdef here, the .h file should handle it.  Why
> doesn't pci.h always include this if it is present?

Only x86 has asm/pci-direct.h. Compiling on any other archs will fail
if we don't put CONFIG_PCI_EARLY here. That's way I added a new config
option CONFIG_PCI_EARLY to drivers/pci/Kconfig and let an arch to select
it. Do you want me to move "#include " to linux/pci.h?

> 
> thanks,
> 
> greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 1/2] serial_core: add pci uart early console support

2015-05-20 Thread Bin Gao
On Wed, May 20, 2015 at 11:16:25AM +0200, Paul Bolle wrote:
> What I should have asked is: do you expect architectures other than X86
> to set HAVE_EARLY_PCI? Because then you should put that Kconfig entry in
> a file reachable by all architectures. Say, in init/Kconfig or in
> drivers/tty/serial/Kconfig.
> 
> (You can also have an entry for HAVE_EARLY_PCI for each arch that needs
> it, but that would be a bit silly.)
> 

The HAVE_EARLY_PCI entry should be actually in generic PCI layer,
i.e. drivers/pci, because it's a PCI feature but only some archs
(currently only x86) support it.
Then an arch with this feature could announce it in arch//Kconfig by:
select HAVE_EARLY_PCI if PCI



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


Re: [PATCH v3 1/2] serial_core: add pci uart early console support

2015-05-20 Thread Bin Gao
On Wed, May 20, 2015 at 07:50:12PM +0200, Paul Bolle wrote:
> That makes more sense. So v4 will put HAVE_EARLY_PCI in a Kconfig under
> drivers/pci/?
> 
Yes.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v4 1/2] serial_core: add pci uart early console support

2015-05-20 Thread Bin Gao
On some Intel Atom SoCs, the legacy IO port UART(0x3F8) is not available.
Instead, a 8250 compatible PCI uart can be used as early console.
This patch adds pci support to the 8250 early console driver uart8250.
For example, to enable pci uart(00:21.3) as early console on these
platforms, append the following line to the kernel command line
(assume baud rate is 115200):
earlyprintk=uart8250,pci32,0:24.2,115200n8

Signed-off-by: Bin Gao 
---
 arch/x86/Kconfig |   1 +
 drivers/pci/Kconfig  |  11 +++
 drivers/tty/serial/earlycon.c|   9 +++
 drivers/tty/serial/serial_core.c | 145 ++-
 4 files changed, 164 insertions(+), 2 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 226d569..bdedd61 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -143,6 +143,7 @@ config X86
select ACPI_LEGACY_TABLES_LOOKUP if ACPI
select X86_FEATURE_NAMES if PROC_FS
select SRCU
+   select PCI_EARLY if PCI
 
 config INSTRUCTION_DECODER
def_bool y
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 7a8f1c5..4f0f055 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -114,4 +114,15 @@ config PCI_LABEL
def_bool y if (DMI || ACPI)
select NLS
 
+config PCI_EARLY
+   bool "Early PCI access"
+   depends on PCI
+   default n
+   help
+ This option indicates that a group of APIs are available (in
+ asm/pci-direct.h) so the kernel can access pci config registers
+ before the PCI subsystem is initialized. Any arch that supports
+ early pci APIs should enable this option which is required  by
+ arch independent codes, e.g. uart8250 pci early console driver.
+
 source "drivers/pci/host/Kconfig"
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index 6dc471e..63ae60e 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -193,6 +193,15 @@ static int __init param_setup_earlycon(char *buf)
 }
 early_param("earlycon", param_setup_earlycon);
 
+/* x86 uses "earlyprintk=xxx", so we keep the compatibility here */
+#ifdef CONFIG_X86
+static int __init param_setup_earlycon_x86(char *buf)
+{
+   return param_setup_earlycon(buf);
+}
+early_param("earlyprintk", param_setup_earlycon_x86);
+#endif
+
 int __init of_setup_earlycon(unsigned long addr,
 int (*setup)(struct earlycon_device *, const char 
*))
 {
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 0b7bb12..19ca2a0 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -34,10 +34,15 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
 
+#ifdef CONFIG_PCI_EARLY
+#include 
+#endif
+
 /*
  * This is used to lock changes in serial line configuration.
  */
@@ -1808,6 +1813,110 @@ uart_get_console(struct uart_port *ports, int nr, 
struct console *co)
return ports + idx;
 }
 
+static int parse_bdf(char *options, char **endp, char delimiter, u8 *val)
+{
+   char str[4]; /* max 3 chars, plus a NULL terminator */
+   char *p = options;
+   int i = 0;
+
+   while (*p) {
+   if (i >= 4)
+   return -EINVAL;
+
+   if (*p == delimiter) {
+   str[i++] = 0;
+   if (endp)
+   *endp = p + 1;
+   return kstrtou8(str, 10, val); /* decimal, no hex */
+   }
+
+   str[i++] = *p++;
+   }
+
+   return -EINVAL;
+}
+
+#ifdef CONFIG_PCI_EARLY
+/*
+ * The whole pci option from the command line is: pci[32],B:D.F[,options]
+ * Examples:
+ * pci,0:21.3,115200n8
+ * pci32,0:21.3
+ * Here pci32 means 8250 UART registers are 32-bit width(regshift = 2).
+ * pci means 8250 UART registers are 8-bit width(regshift = 0).
+ * B,D and F are bus, device and function, in decimal(not hex).
+ * The additional options(115200n8) would be parsed by the earlycon framework.
+ *
+ * @options: the pci options
+ * @phys: the pointer to return pci mem or io address
+ * return: <0: error
+ *  0: pci mem
+ *  1: pci io
+ */
+static int parse_pci_options(char *options, unsigned long *phys)
+{
+   u8 bus, dev, func;
+   char *endp;
+   u64 bar0;
+   u16 cmd;
+   int pci_io = 0;
+
+   if (!early_pci_allowed()) {
+   pr_err("earlycon pci not available(early pci not allowed)\n");
+   return -EINVAL;
+   }
+
+   /* We come here with options=B:D.F[,options] */
+   if (parse_bdf(options, &endp, ':', &bus))
+   goto failed;
+
+   if (parse_bdf(endp, &endp, '.', &dev))
+   goto failed;
+
+   if (parse_bdf(endp, &endp, ',', &func))
+   go

[PATCH v4 2/2] arch/x86: remove pci uart early console from early_prink.c

2015-05-20 Thread Bin Gao
The arch independent uart8250 early console driver has good
support for memory mapped and io port based 8250 uarts. Since
pci is arch independent so it's natural to extend uart8250 to
support mem, io and pci. Hence pci uart early console in
arch/x86/kernel_printk.c by the following commit:
'commit 5140fda16051 ("Specify PCI based UART for earlyprintk")'
is removed. And its equivalent function will be available from
uart8250 early console driver.

Signed-off-by: Bin Gao 
---
 arch/x86/kernel/early_printk.c | 180 -
 1 file changed, 15 insertions(+), 165 deletions(-)

diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index 89427d8..00c2e2a 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -19,7 +19,6 @@
 #include 
 #include 
 #include 
-#include 
 
 /* Simple VGA output */
 #define VGABASE(__ISA_IO_base + 0xb8000)
@@ -77,7 +76,7 @@ static struct console early_vga_console = {
 
 /* Serial functions loosely based on a similar package from Klaus P. Gerlicher 
*/
 
-static unsigned long early_serial_base = 0x3f8;  /* ttyS0 */
+static int early_serial_base = 0x3f8;  /* ttyS0 */
 
 #define XMTRDY  0x20
 
@@ -95,26 +94,13 @@ static unsigned long early_serial_base = 0x3f8;  /* ttyS0 */
 #define DLL 0   /*  Divisor Latch Low */
 #define DLH 1   /*  Divisor latch High*/
 
-static unsigned int io_serial_in(unsigned long addr, int offset)
-{
-   return inb(addr + offset);
-}
-
-static void io_serial_out(unsigned long addr, int offset, int value)
-{
-   outb(value, addr + offset);
-}
-
-static unsigned int (*serial_in)(unsigned long addr, int offset) = 
io_serial_in;
-static void (*serial_out)(unsigned long addr, int offset, int value) = 
io_serial_out;
-
 static int early_serial_putc(unsigned char ch)
 {
unsigned timeout = 0x;
 
-   while ((serial_in(early_serial_base, LSR) & XMTRDY) == 0 && --timeout)
+   while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
cpu_relax();
-   serial_out(early_serial_base, TXR, ch);
+   outb(ch, early_serial_base + TXR);
return timeout ? 0 : -1;
 }
 
@@ -128,28 +114,13 @@ static void early_serial_write(struct console *con, const 
char *s, unsigned n)
}
 }
 
-static __init void early_serial_hw_init(unsigned divisor)
-{
-   unsigned char c;
-
-   serial_out(early_serial_base, LCR, 0x3);/* 8n1 */
-   serial_out(early_serial_base, IER, 0);  /* no interrupt */
-   serial_out(early_serial_base, FCR, 0);  /* no fifo */
-   serial_out(early_serial_base, MCR, 0x3);/* DTR + RTS */
-
-   c = serial_in(early_serial_base, LCR);
-   serial_out(early_serial_base, LCR, c | DLAB);
-   serial_out(early_serial_base, DLL, divisor & 0xff);
-   serial_out(early_serial_base, DLH, (divisor >> 8) & 0xff);
-   serial_out(early_serial_base, LCR, c & ~DLAB);
-}
-
 #define DEFAULT_BAUD 9600
 
 static __init void early_serial_init(char *s)
 {
+   unsigned char c;
unsigned divisor;
-   unsigned long baud = DEFAULT_BAUD;
+   unsigned baud = DEFAULT_BAUD;
char *e;
 
if (*s == ',')
@@ -174,138 +145,23 @@ static __init void early_serial_init(char *s)
s++;
}
 
-   if (*s) {
-   if (kstrtoul(s, 0, &baud) < 0 || baud == 0)
-   baud = DEFAULT_BAUD;
-   }
-
-   /* Convert from baud to divisor value */
-   divisor = 115200 / baud;
-
-   /* These will always be IO based ports */
-   serial_in = io_serial_in;
-   serial_out = io_serial_out;
-
-   /* Set up the HW */
-   early_serial_hw_init(divisor);
-}
-
-#ifdef CONFIG_PCI
-static void mem32_serial_out(unsigned long addr, int offset, int value)
-{
-   u32 *vaddr = (u32 *)addr;
-   /* shift implied by pointer type */
-   writel(value, vaddr + offset);
-}
-
-static unsigned int mem32_serial_in(unsigned long addr, int offset)
-{
-   u32 *vaddr = (u32 *)addr;
-   /* shift implied by pointer type */
-   return readl(vaddr + offset);
-}
-
-/*
- * early_pci_serial_init()
- *
- * This function is invoked when the early_printk param starts with "pciserial"
- * The rest of the param should be ",B:D.F,baud" where B, D & F describe the
- * location of a PCI device that must be a UART device.
- */
-static __init void early_pci_serial_init(char *s)
-{
-   unsigned divisor;
-   unsigned long baud = DEFAULT_BAUD;
-   u8 bus, slot, func;
-   u32 classcode, bar0;
-   u16 cmdreg;
-   char *e;
-
-
-   /*
-* First, part the param to get the BDF values
-*/
-   if (*s == ',')
-   ++s;
-
-   if (*s == 0)
-   return;
-
-   bus = (u8)si

[PATCH v4 1/2] serial_core: add pci uart early console support

2015-05-21 Thread Bin Gao
On some Intel Atom SoCs, the legacy IO port UART(0x3F8) is not available.
Instead, a 8250 compatible PCI uart can be used as early console.
This patch adds pci support to the 8250 early console driver uart8250.
For example, to enable pci uart(00:21.3) as early console on these
platforms, append the following line to the kernel command line
(assume baud rate is 115200):
earlyprintk=uart8250,pci32,0:24.2,115200n8

Signed-off-by: Bin Gao 
---
Changes in v4:
 - moved PCI_EARLY definition from arch/x86/Kconfig to drivers/pci/Kconfig
 - added 'earlyprintk' for x86 as alias to the early param 'earlycon'

 arch/x86/Kconfig |   1 +
 drivers/pci/Kconfig  |  11 +++
 drivers/tty/serial/earlycon.c|   9 +++
 drivers/tty/serial/serial_core.c | 145 ++-
 4 files changed, 164 insertions(+), 2 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 226d569..bdedd61 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -143,6 +143,7 @@ config X86
select ACPI_LEGACY_TABLES_LOOKUP if ACPI
select X86_FEATURE_NAMES if PROC_FS
select SRCU
+   select PCI_EARLY if PCI
 
 config INSTRUCTION_DECODER
def_bool y
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 7a8f1c5..4f0f055 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -114,4 +114,15 @@ config PCI_LABEL
def_bool y if (DMI || ACPI)
select NLS
 
+config PCI_EARLY
+   bool "Early PCI access"
+   depends on PCI
+   default n
+   help
+ This option indicates that a group of APIs are available (in
+ asm/pci-direct.h) so the kernel can access pci config registers
+ before the PCI subsystem is initialized. Any arch that supports
+ early pci APIs should enable this option which is required  by
+ arch independent codes, e.g. uart8250 pci early console driver.
+
 source "drivers/pci/host/Kconfig"
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index 6dc471e..63ae60e 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -193,6 +193,15 @@ static int __init param_setup_earlycon(char *buf)
 }
 early_param("earlycon", param_setup_earlycon);
 
+/* x86 uses "earlyprintk=xxx", so we keep the compatibility here */
+#ifdef CONFIG_X86
+static int __init param_setup_earlycon_x86(char *buf)
+{
+   return param_setup_earlycon(buf);
+}
+early_param("earlyprintk", param_setup_earlycon_x86);
+#endif
+
 int __init of_setup_earlycon(unsigned long addr,
 int (*setup)(struct earlycon_device *, const char 
*))
 {
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 0b7bb12..19ca2a0 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -34,10 +34,15 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
 
+#ifdef CONFIG_PCI_EARLY
+#include 
+#endif
+
 /*
  * This is used to lock changes in serial line configuration.
  */
@@ -1808,6 +1813,110 @@ uart_get_console(struct uart_port *ports, int nr, 
struct console *co)
return ports + idx;
 }
 
+static int parse_bdf(char *options, char **endp, char delimiter, u8 *val)
+{
+   char str[4]; /* max 3 chars, plus a NULL terminator */
+   char *p = options;
+   int i = 0;
+
+   while (*p) {
+   if (i >= 4)
+   return -EINVAL;
+
+   if (*p == delimiter) {
+   str[i++] = 0;
+   if (endp)
+   *endp = p + 1;
+   return kstrtou8(str, 10, val); /* decimal, no hex */
+   }
+
+   str[i++] = *p++;
+   }
+
+   return -EINVAL;
+}
+
+#ifdef CONFIG_PCI_EARLY
+/*
+ * The whole pci option from the command line is: pci[32],B:D.F[,options]
+ * Examples:
+ * pci,0:21.3,115200n8
+ * pci32,0:21.3
+ * Here pci32 means 8250 UART registers are 32-bit width(regshift = 2).
+ * pci means 8250 UART registers are 8-bit width(regshift = 0).
+ * B,D and F are bus, device and function, in decimal(not hex).
+ * The additional options(115200n8) would be parsed by the earlycon framework.
+ *
+ * @options: the pci options
+ * @phys: the pointer to return pci mem or io address
+ * return: <0: error
+ *  0: pci mem
+ *  1: pci io
+ */
+static int parse_pci_options(char *options, unsigned long *phys)
+{
+   u8 bus, dev, func;
+   char *endp;
+   u64 bar0;
+   u16 cmd;
+   int pci_io = 0;
+
+   if (!early_pci_allowed()) {
+   pr_err("earlycon pci not available(early pci not allowed)\n");
+   return -EINVAL;
+   }
+
+   /* We come here with options=B:D.F[,options] */
+   if (parse_bdf(options, &endp, ':', &bus))
+   goto failed;
+
+   if (parse_b

Re: [PATCH v4 1/2] serial_core: add pci uart early console support

2015-05-21 Thread Bin Gao
On Wed, May 20, 2015 at 09:31:45PM -0700, Greg Kroah-Hartman wrote:
> What changed in this version?
> 
> You can't just put "v4" without giving us some hint as to the
> differences here, sorry.

I just resent [PATCH v4 1/2] with "Changes in v4" added.
There is no change for patch 2/2 since the first version, so I didn't
resend [PATCH v4 2/2].

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


[PATCH v4 1/2] serial_core: add pci uart early console support

2015-05-22 Thread Bin Gao
On some Intel Atom SoCs, the legacy IO port UART(0x3F8) is not available.
Instead, a 8250 compatible PCI uart can be used as early console.
This patch adds pci support to the 8250 early console driver uart8250.
For example, to enable pci uart(00:21.3) as early console on these
platforms, append the following line to the kernel command line
(assume baud rate is 115200):
earlyprintk=uart8250,pci32,0:24.2,115200n8

Signed-off-by: Bin Gao 
---
Changes in v4:
 - moved PCI_EARLY definition from arch/x86/Kconfig to drivers/pci/Kconfig
 - added 'earlyprintk' for x86 as alias to the early param 'earlycon'
 arch/x86/Kconfig |   1 +
 drivers/pci/Kconfig  |  11 +++
 drivers/tty/serial/earlycon.c|   9 +++
 drivers/tty/serial/serial_core.c | 145 ++-
 4 files changed, 164 insertions(+), 2 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 226d569..bdedd61 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -143,6 +143,7 @@ config X86
select ACPI_LEGACY_TABLES_LOOKUP if ACPI
select X86_FEATURE_NAMES if PROC_FS
select SRCU
+   select PCI_EARLY if PCI
 
 config INSTRUCTION_DECODER
def_bool y
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 7a8f1c5..4f0f055 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -114,4 +114,15 @@ config PCI_LABEL
def_bool y if (DMI || ACPI)
select NLS
 
+config PCI_EARLY
+   bool "Early PCI access"
+   depends on PCI
+   default n
+   help
+ This option indicates that a group of APIs are available (in
+ asm/pci-direct.h) so the kernel can access pci config registers
+ before the PCI subsystem is initialized. Any arch that supports
+ early pci APIs should enable this option which is required  by
+ arch independent codes, e.g. uart8250 pci early console driver.
+
 source "drivers/pci/host/Kconfig"
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index 6dc471e..63ae60e 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -193,6 +193,15 @@ static int __init param_setup_earlycon(char *buf)
 }
 early_param("earlycon", param_setup_earlycon);
 
+/* x86 uses "earlyprintk=xxx", so we keep the compatibility here */
+#ifdef CONFIG_X86
+static int __init param_setup_earlycon_x86(char *buf)
+{
+   return param_setup_earlycon(buf);
+}
+early_param("earlyprintk", param_setup_earlycon_x86);
+#endif
+
 int __init of_setup_earlycon(unsigned long addr,
 int (*setup)(struct earlycon_device *, const char 
*))
 {
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 0b7bb12..19ca2a0 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -34,10 +34,15 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
 
+#ifdef CONFIG_PCI_EARLY
+#include 
+#endif
+
 /*
  * This is used to lock changes in serial line configuration.
  */
@@ -1808,6 +1813,110 @@ uart_get_console(struct uart_port *ports, int nr, 
struct console *co)
return ports + idx;
 }
 
+static int parse_bdf(char *options, char **endp, char delimiter, u8 *val)
+{
+   char str[4]; /* max 3 chars, plus a NULL terminator */
+   char *p = options;
+   int i = 0;
+
+   while (*p) {
+   if (i >= 4)
+   return -EINVAL;
+
+   if (*p == delimiter) {
+   str[i++] = 0;
+   if (endp)
+   *endp = p + 1;
+   return kstrtou8(str, 10, val); /* decimal, no hex */
+   }
+
+   str[i++] = *p++;
+   }
+
+   return -EINVAL;
+}
+
+#ifdef CONFIG_PCI_EARLY
+/*
+ * The whole pci option from the command line is: pci[32],B:D.F[,options]
+ * Examples:
+ * pci,0:21.3,115200n8
+ * pci32,0:21.3
+ * Here pci32 means 8250 UART registers are 32-bit width(regshift = 2).
+ * pci means 8250 UART registers are 8-bit width(regshift = 0).
+ * B,D and F are bus, device and function, in decimal(not hex).
+ * The additional options(115200n8) would be parsed by the earlycon framework.
+ *
+ * @options: the pci options
+ * @phys: the pointer to return pci mem or io address
+ * return: <0: error
+ *  0: pci mem
+ *  1: pci io
+ */
+static int parse_pci_options(char *options, unsigned long *phys)
+{
+   u8 bus, dev, func;
+   char *endp;
+   u64 bar0;
+   u16 cmd;
+   int pci_io = 0;
+
+   if (!early_pci_allowed()) {
+   pr_err("earlycon pci not available(early pci not allowed)\n");
+   return -EINVAL;
+   }
+
+   /* We come here with options=B:D.F[,options] */
+   if (parse_bdf(options, &endp, ':', &bus))
+   goto failed;
+
+   if (parse_b

[PATCH v4 2/2] arch/x86: remove pci uart early console from early_prink.c

2015-05-22 Thread Bin Gao
The arch independent uart8250 early console driver has good
support for memory mapped and io port based 8250 uarts. Since
pci is arch independent so it's natural to extend uart8250 to
support mem, io and pci. Hence pci uart early console in
arch/x86/kernel_printk.c by the following commit:
'commit 5140fda16051 ("Specify PCI based UART for earlyprintk")'
is removed. And its equivalent function will be available from
uart8250 early console driver.

Signed-off-by: Bin Gao 
---
 arch/x86/kernel/early_printk.c | 180 -
 1 file changed, 15 insertions(+), 165 deletions(-)

diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index 89427d8..00c2e2a 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -19,7 +19,6 @@
 #include 
 #include 
 #include 
-#include 
 
 /* Simple VGA output */
 #define VGABASE(__ISA_IO_base + 0xb8000)
@@ -77,7 +76,7 @@ static struct console early_vga_console = {
 
 /* Serial functions loosely based on a similar package from Klaus P. Gerlicher 
*/
 
-static unsigned long early_serial_base = 0x3f8;  /* ttyS0 */
+static int early_serial_base = 0x3f8;  /* ttyS0 */
 
 #define XMTRDY  0x20
 
@@ -95,26 +94,13 @@ static unsigned long early_serial_base = 0x3f8;  /* ttyS0 */
 #define DLL 0   /*  Divisor Latch Low */
 #define DLH 1   /*  Divisor latch High*/
 
-static unsigned int io_serial_in(unsigned long addr, int offset)
-{
-   return inb(addr + offset);
-}
-
-static void io_serial_out(unsigned long addr, int offset, int value)
-{
-   outb(value, addr + offset);
-}
-
-static unsigned int (*serial_in)(unsigned long addr, int offset) = 
io_serial_in;
-static void (*serial_out)(unsigned long addr, int offset, int value) = 
io_serial_out;
-
 static int early_serial_putc(unsigned char ch)
 {
unsigned timeout = 0x;
 
-   while ((serial_in(early_serial_base, LSR) & XMTRDY) == 0 && --timeout)
+   while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
cpu_relax();
-   serial_out(early_serial_base, TXR, ch);
+   outb(ch, early_serial_base + TXR);
return timeout ? 0 : -1;
 }
 
@@ -128,28 +114,13 @@ static void early_serial_write(struct console *con, const 
char *s, unsigned n)
}
 }
 
-static __init void early_serial_hw_init(unsigned divisor)
-{
-   unsigned char c;
-
-   serial_out(early_serial_base, LCR, 0x3);/* 8n1 */
-   serial_out(early_serial_base, IER, 0);  /* no interrupt */
-   serial_out(early_serial_base, FCR, 0);  /* no fifo */
-   serial_out(early_serial_base, MCR, 0x3);/* DTR + RTS */
-
-   c = serial_in(early_serial_base, LCR);
-   serial_out(early_serial_base, LCR, c | DLAB);
-   serial_out(early_serial_base, DLL, divisor & 0xff);
-   serial_out(early_serial_base, DLH, (divisor >> 8) & 0xff);
-   serial_out(early_serial_base, LCR, c & ~DLAB);
-}
-
 #define DEFAULT_BAUD 9600
 
 static __init void early_serial_init(char *s)
 {
+   unsigned char c;
unsigned divisor;
-   unsigned long baud = DEFAULT_BAUD;
+   unsigned baud = DEFAULT_BAUD;
char *e;
 
if (*s == ',')
@@ -174,138 +145,23 @@ static __init void early_serial_init(char *s)
s++;
}
 
-   if (*s) {
-   if (kstrtoul(s, 0, &baud) < 0 || baud == 0)
-   baud = DEFAULT_BAUD;
-   }
-
-   /* Convert from baud to divisor value */
-   divisor = 115200 / baud;
-
-   /* These will always be IO based ports */
-   serial_in = io_serial_in;
-   serial_out = io_serial_out;
-
-   /* Set up the HW */
-   early_serial_hw_init(divisor);
-}
-
-#ifdef CONFIG_PCI
-static void mem32_serial_out(unsigned long addr, int offset, int value)
-{
-   u32 *vaddr = (u32 *)addr;
-   /* shift implied by pointer type */
-   writel(value, vaddr + offset);
-}
-
-static unsigned int mem32_serial_in(unsigned long addr, int offset)
-{
-   u32 *vaddr = (u32 *)addr;
-   /* shift implied by pointer type */
-   return readl(vaddr + offset);
-}
-
-/*
- * early_pci_serial_init()
- *
- * This function is invoked when the early_printk param starts with "pciserial"
- * The rest of the param should be ",B:D.F,baud" where B, D & F describe the
- * location of a PCI device that must be a UART device.
- */
-static __init void early_pci_serial_init(char *s)
-{
-   unsigned divisor;
-   unsigned long baud = DEFAULT_BAUD;
-   u8 bus, slot, func;
-   u32 classcode, bar0;
-   u16 cmdreg;
-   char *e;
-
-
-   /*
-* First, part the param to get the BDF values
-*/
-   if (*s == ',')
-   ++s;
-
-   if (*s == 0)
-   return;
-
-   bus = (u8)si

Re: serial_core: add pci uart early console support

2015-05-14 Thread Bin Gao
> On Wed, May 13, 2015 at 11:08:44PM +0100, One Thousand Gnomes wrote:
> 
> We've already got support for this
> 
> commit ea9e9d8029020d438b0717ffddf65140fda16051
> 
> 
> I actually think the fact you've put it into drivers/tty is better as PCI
> is generic and PCI serial boot likewise. However it ought to use the same
> command line interface (with extensions) to be compatible with the
> existing arch/x86 code, and to remove the arch/x86 version if you are
> doing so.
> 
> Alan

So now I'm sending two patches:
[PATCH 1/2] serial_core: add pci uart early console support
[PATCH 2/2] arch/x86: remove pci uart early console from early_prink.c
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/2] serial_core: add pci uart early console support

2015-05-14 Thread Bin Gao
>From 0d02240f022c8aca593c42a7220699dbbe37f292 Mon Sep 17 00:00:00 2001
From: Bin Gao 
Date: Tue, 12 May 2015 16:40:27 -0700
Subject: [PATCH] serial_core: add pci uart early console support

On some Intel Atom SoCs, the legacy IO port UART(0x3F8) is not available.
Instead, a 8250 compatible PCI uart can be used as early console.
This patch adds pci support to the 8250 early console driver uart8250.
For example, to enable pci uart(00:21.3) as early console on these
platforms, append the following line to the kernel command line
(assume baud rate is 115200):
earlyprintk=uart8250,pci32,0:24.2,115200n8

Signed-off-by: Bin Gao 
---
 drivers/tty/serial/earlycon.c|   6 ++
 drivers/tty/serial/serial_core.c | 140 ++-
 2 files changed, 144 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index 5fdc9f3..586d84b 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -196,7 +196,13 @@ static int __init param_setup_earlycon(char *buf)
}
return err;
 }
+
+/* x86 uses "earlyprintk=xxx", so we keep the compatibility here */
+#ifdef CONFIG_X86
+early_param("earlyprintk", param_setup_earlycon);
+#else
 early_param("earlycon", param_setup_earlycon);
+#endif
 
 int __init of_setup_earlycon(unsigned long addr,
 int (*setup)(struct earlycon_device *, const char 
*))
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 0b7bb12..221143c 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -34,10 +34,16 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
 
+/* Only x86 has early pci access APIs */
+#if defined(CONFIG_PCI) && defined(CONFIG_X86)
+#include 
+#endif
+
 /*
  * This is used to lock changes in serial line configuration.
  */
@@ -1808,6 +1814,98 @@ uart_get_console(struct uart_port *ports, int nr, struct 
console *co)
return ports + idx;
 }
 
+#if defined(CONFIG_PCI) && defined(CONFIG_X86)
+static int parse_bdf(char *options, char **endp, char delimiter, u8 *val)
+{
+   char str[4]; /* max 3 chars, plus a NULL terminator */
+   char *p = options;
+   int i = 0;
+
+   while (*p) {
+   if (i >= 4)
+   return -EINVAL;
+
+   if (*p == delimiter) {
+   str[i++] = 0;
+   if (endp)
+   *endp = p + 1;
+   return kstrtou8(str, 10, val); /* decimal, no hex */
+   }
+
+   str[i++] = *p++;
+   }
+
+   return -EINVAL;
+}
+
+/*
+ * The whole pci option from the command line is: pci[32],B:D.F[,options]
+ * Examples:
+ * pci,0:21.3,115200n8
+ * pci32,0:21.3
+ * Here pci32 means 8250 UART registers are 32-bit width(regshift = 2).
+ * pci means 8250 UART registers are 8-bit width(regshift = 0).
+ * B,D and F are bus, device and function, in decimal(not hex).
+ * The additional options(115200n8) would be parsed by the earlycon framework.
+ *
+ * @options: the pci options
+ * @phys: the pointer to return pci mem or io address
+ * return: <0: error
+ *  0: pci mem
+ *  1: pci io
+ */
+static int parse_pci_options(char *options, unsigned long *phys)
+{
+   u8 bus, dev, func;
+   char *endp;
+   u64 bar0;
+   u16 cmd;
+   int pci_io = 0;
+
+   /* We come here with options=B:D.F[,options] */
+   if (parse_bdf(options, &endp, ':', &bus))
+   goto failed;
+
+   if (parse_bdf(endp, &endp, '.', &dev))
+   goto failed;
+
+   if (parse_bdf(endp, &endp, ',', &func))
+   goto failed;
+
+   /*
+* On these platforms class code in pci config is broken,
+* so skip checking it.
+*/
+
+   bar0 = read_pci_config(bus, dev, func, PCI_BASE_ADDRESS_0);
+
+   /* The BAR is IO or Memory? */
+   if ((bar0 & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
+   pci_io = 1;
+
+   if ((bar0 & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+   PCI_BASE_ADDRESS_MEM_TYPE_64)
+   bar0 |= (u64)read_pci_config(bus, dev, func,
+   PCI_BASE_ADDRESS_0 + 4) << 32;
+
+   *phys = bar0 & (pci_io ? PCI_BASE_ADDRESS_IO_MASK :
+PCI_BASE_ADDRESS_MEM_MASK);
+
+   /* Enable address decoding */
+   cmd = read_pci_config_16(bus, dev, func, PCI_COMMAND);
+   write_pci_config_16(bus, dev, func, PCI_COMMAND,
+   cmd | (pci_io ? PCI_COMMAND_IO : PCI_COMMAND_MEMORY));
+
+   pr_info("Use 8250 uart at PCI :%02u:%02u.%01u as early console\n",
+   bus, dev, func);
+   return pci_io;
+
+failed:
+   pr

[PATCH 2/2] arch/x86: remove pci uart early console from early_prink.c

2015-05-14 Thread Bin Gao
>From 78ab0810176c544e2b6f14ca8b19c90d339fa6f1 Mon Sep 17 00:00:00 2001
From: Bin Gao 
Date: Thu, 14 May 2015 15:49:58 -0700
Subject: [PATCH] arch/x86: remove pci uart early console from early_prink.c

The arch independent uart8250 early console driver has good
support for memory mapped and io port based 8250 uarts. Since
pci is arch independent so it's natural to extend uart8250 to
support mem, io and pci. Hence pci uart early console in
arch/x86/kernel_printk.c by the following commit:
'commit 5140fda16051 ("Specify PCI based UART for earlyprintk")'
is removed. And its equivalent function will be available from
uart8250 early console driver.

This patch comes with another patch:
serial_core: add pci uart early console support

Signed-off-by: Bin Gao 
---
 arch/x86/kernel/early_printk.c | 180 -
 1 file changed, 15 insertions(+), 165 deletions(-)

diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index 89427d8..00c2e2a 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -19,7 +19,6 @@
 #include 
 #include 
 #include 
-#include 
 
 /* Simple VGA output */
 #define VGABASE(__ISA_IO_base + 0xb8000)
@@ -77,7 +76,7 @@ static struct console early_vga_console = {
 
 /* Serial functions loosely based on a similar package from Klaus P. Gerlicher 
*/
 
-static unsigned long early_serial_base = 0x3f8;  /* ttyS0 */
+static int early_serial_base = 0x3f8;  /* ttyS0 */
 
 #define XMTRDY  0x20
 
@@ -95,26 +94,13 @@ static unsigned long early_serial_base = 0x3f8;  /* ttyS0 */
 #define DLL 0   /*  Divisor Latch Low */
 #define DLH 1   /*  Divisor latch High*/
 
-static unsigned int io_serial_in(unsigned long addr, int offset)
-{
-   return inb(addr + offset);
-}
-
-static void io_serial_out(unsigned long addr, int offset, int value)
-{
-   outb(value, addr + offset);
-}
-
-static unsigned int (*serial_in)(unsigned long addr, int offset) = 
io_serial_in;
-static void (*serial_out)(unsigned long addr, int offset, int value) = 
io_serial_out;
-
 static int early_serial_putc(unsigned char ch)
 {
unsigned timeout = 0x;
 
-   while ((serial_in(early_serial_base, LSR) & XMTRDY) == 0 && --timeout)
+   while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
cpu_relax();
-   serial_out(early_serial_base, TXR, ch);
+   outb(ch, early_serial_base + TXR);
return timeout ? 0 : -1;
 }
 
@@ -128,28 +114,13 @@ static void early_serial_write(struct console *con, const 
char *s, unsigned n)
}
 }
 
-static __init void early_serial_hw_init(unsigned divisor)
-{
-   unsigned char c;
-
-   serial_out(early_serial_base, LCR, 0x3);/* 8n1 */
-   serial_out(early_serial_base, IER, 0);  /* no interrupt */
-   serial_out(early_serial_base, FCR, 0);  /* no fifo */
-   serial_out(early_serial_base, MCR, 0x3);/* DTR + RTS */
-
-   c = serial_in(early_serial_base, LCR);
-   serial_out(early_serial_base, LCR, c | DLAB);
-   serial_out(early_serial_base, DLL, divisor & 0xff);
-   serial_out(early_serial_base, DLH, (divisor >> 8) & 0xff);
-   serial_out(early_serial_base, LCR, c & ~DLAB);
-}
-
 #define DEFAULT_BAUD 9600
 
 static __init void early_serial_init(char *s)
 {
+   unsigned char c;
unsigned divisor;
-   unsigned long baud = DEFAULT_BAUD;
+   unsigned baud = DEFAULT_BAUD;
char *e;
 
if (*s == ',')
@@ -174,138 +145,23 @@ static __init void early_serial_init(char *s)
s++;
}
 
-   if (*s) {
-   if (kstrtoul(s, 0, &baud) < 0 || baud == 0)
-   baud = DEFAULT_BAUD;
-   }
-
-   /* Convert from baud to divisor value */
-   divisor = 115200 / baud;
-
-   /* These will always be IO based ports */
-   serial_in = io_serial_in;
-   serial_out = io_serial_out;
-
-   /* Set up the HW */
-   early_serial_hw_init(divisor);
-}
-
-#ifdef CONFIG_PCI
-static void mem32_serial_out(unsigned long addr, int offset, int value)
-{
-   u32 *vaddr = (u32 *)addr;
-   /* shift implied by pointer type */
-   writel(value, vaddr + offset);
-}
-
-static unsigned int mem32_serial_in(unsigned long addr, int offset)
-{
-   u32 *vaddr = (u32 *)addr;
-   /* shift implied by pointer type */
-   return readl(vaddr + offset);
-}
-
-/*
- * early_pci_serial_init()
- *
- * This function is invoked when the early_printk param starts with "pciserial"
- * The rest of the param should be ",B:D.F,baud" where B, D & F describe the
- * location of a PCI device that must be a UART device.
- */
-static __init void early_pci_serial_init(char *s)
-{
-   unsigned divisor;
-   unsigned long baud = DEFAULT_BAUD;
-   u8 bus, slot

[PATCH v2 1/2] serial_core: add pci uart early console support

2015-05-14 Thread Bin Gao
On some Intel Atom SoCs, the legacy IO port UART(0x3F8) is not available.
Instead, a 8250 compatible PCI uart can be used as early console.
This patch adds pci support to the 8250 early console driver uart8250.
For example, to enable pci uart(00:21.3) as early console on these
platforms, append the following line to the kernel command line
(assume baud rate is 115200):
earlyprintk=uart8250,pci32,0:24.2,115200n8

Signed-off-by: Bin Gao 
---
 drivers/tty/serial/earlycon.c|   6 ++
 drivers/tty/serial/serial_core.c | 140 ++-
 2 files changed, 144 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index 5fdc9f3..586d84b 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -196,7 +196,13 @@ static int __init param_setup_earlycon(char *buf)
}
return err;
 }
+
+/* x86 uses "earlyprintk=xxx", so we keep the compatibility here */
+#ifdef CONFIG_X86
+early_param("earlyprintk", param_setup_earlycon);
+#else
 early_param("earlycon", param_setup_earlycon);
+#endif
 
 int __init of_setup_earlycon(unsigned long addr,
 int (*setup)(struct earlycon_device *, const char 
*))
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 0b7bb12..221143c 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -34,10 +34,16 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
 
+/* Only x86 has early pci access APIs */
+#if defined(CONFIG_PCI) && defined(CONFIG_X86)
+#include 
+#endif
+
 /*
  * This is used to lock changes in serial line configuration.
  */
@@ -1808,6 +1814,98 @@ uart_get_console(struct uart_port *ports, int nr, struct 
console *co)
return ports + idx;
 }
 
+#if defined(CONFIG_PCI) && defined(CONFIG_X86)
+static int parse_bdf(char *options, char **endp, char delimiter, u8 *val)
+{
+   char str[4]; /* max 3 chars, plus a NULL terminator */
+   char *p = options;
+   int i = 0;
+
+   while (*p) {
+   if (i >= 4)
+   return -EINVAL;
+
+   if (*p == delimiter) {
+   str[i++] = 0;
+   if (endp)
+   *endp = p + 1;
+   return kstrtou8(str, 10, val); /* decimal, no hex */
+   }
+
+   str[i++] = *p++;
+   }
+
+   return -EINVAL;
+}
+
+/*
+ * The whole pci option from the command line is: pci[32],B:D.F[,options]
+ * Examples:
+ * pci,0:21.3,115200n8
+ * pci32,0:21.3
+ * Here pci32 means 8250 UART registers are 32-bit width(regshift = 2).
+ * pci means 8250 UART registers are 8-bit width(regshift = 0).
+ * B,D and F are bus, device and function, in decimal(not hex).
+ * The additional options(115200n8) would be parsed by the earlycon framework.
+ *
+ * @options: the pci options
+ * @phys: the pointer to return pci mem or io address
+ * return: <0: error
+ *  0: pci mem
+ *  1: pci io
+ */
+static int parse_pci_options(char *options, unsigned long *phys)
+{
+   u8 bus, dev, func;
+   char *endp;
+   u64 bar0;
+   u16 cmd;
+   int pci_io = 0;
+
+   /* We come here with options=B:D.F[,options] */
+   if (parse_bdf(options, &endp, ':', &bus))
+   goto failed;
+
+   if (parse_bdf(endp, &endp, '.', &dev))
+   goto failed;
+
+   if (parse_bdf(endp, &endp, ',', &func))
+   goto failed;
+
+   /*
+* On these platforms class code in pci config is broken,
+* so skip checking it.
+*/
+
+   bar0 = read_pci_config(bus, dev, func, PCI_BASE_ADDRESS_0);
+
+   /* The BAR is IO or Memory? */
+   if ((bar0 & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
+   pci_io = 1;
+
+   if ((bar0 & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+   PCI_BASE_ADDRESS_MEM_TYPE_64)
+   bar0 |= (u64)read_pci_config(bus, dev, func,
+   PCI_BASE_ADDRESS_0 + 4) << 32;
+
+   *phys = bar0 & (pci_io ? PCI_BASE_ADDRESS_IO_MASK :
+PCI_BASE_ADDRESS_MEM_MASK);
+
+   /* Enable address decoding */
+   cmd = read_pci_config_16(bus, dev, func, PCI_COMMAND);
+   write_pci_config_16(bus, dev, func, PCI_COMMAND,
+   cmd | (pci_io ? PCI_COMMAND_IO : PCI_COMMAND_MEMORY));
+
+   pr_info("Use 8250 uart at PCI :%02u:%02u.%01u as early console\n",
+   bus, dev, func);
+   return pci_io;
+
+failed:
+   pr_err("Invalid earlycon pci parameters\n");
+   return -EINVAL;
+}
+#endif
+
 /**
  * uart_parse_earlycon - Parse earlycon options
  * @p:   ptr to 2nd field (ie., just be

[PATCH v2 2/2] arch/x86: remove pci uart early console from early_prink.c

2015-05-14 Thread Bin Gao
The arch independent uart8250 early console driver has good
support for memory mapped and io port based 8250 uarts. Since
pci is arch independent so it's natural to extend uart8250 to
support mem, io and pci. Hence pci uart early console in
arch/x86/kernel_printk.c by the following commit:
'commit 5140fda16051 ("Specify PCI based UART for earlyprintk")'
is removed. And its equivalent function will be available from
uart8250 early console driver.

Signed-off-by: Bin Gao 
---
 arch/x86/kernel/early_printk.c | 180 -
 1 file changed, 15 insertions(+), 165 deletions(-)

diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index 89427d8..00c2e2a 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -19,7 +19,6 @@
 #include 
 #include 
 #include 
-#include 
 
 /* Simple VGA output */
 #define VGABASE(__ISA_IO_base + 0xb8000)
@@ -77,7 +76,7 @@ static struct console early_vga_console = {
 
 /* Serial functions loosely based on a similar package from Klaus P. Gerlicher 
*/
 
-static unsigned long early_serial_base = 0x3f8;  /* ttyS0 */
+static int early_serial_base = 0x3f8;  /* ttyS0 */
 
 #define XMTRDY  0x20
 
@@ -95,26 +94,13 @@ static unsigned long early_serial_base = 0x3f8;  /* ttyS0 */
 #define DLL 0   /*  Divisor Latch Low */
 #define DLH 1   /*  Divisor latch High*/
 
-static unsigned int io_serial_in(unsigned long addr, int offset)
-{
-   return inb(addr + offset);
-}
-
-static void io_serial_out(unsigned long addr, int offset, int value)
-{
-   outb(value, addr + offset);
-}
-
-static unsigned int (*serial_in)(unsigned long addr, int offset) = 
io_serial_in;
-static void (*serial_out)(unsigned long addr, int offset, int value) = 
io_serial_out;
-
 static int early_serial_putc(unsigned char ch)
 {
unsigned timeout = 0x;
 
-   while ((serial_in(early_serial_base, LSR) & XMTRDY) == 0 && --timeout)
+   while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
cpu_relax();
-   serial_out(early_serial_base, TXR, ch);
+   outb(ch, early_serial_base + TXR);
return timeout ? 0 : -1;
 }
 
@@ -128,28 +114,13 @@ static void early_serial_write(struct console *con, const 
char *s, unsigned n)
}
 }
 
-static __init void early_serial_hw_init(unsigned divisor)
-{
-   unsigned char c;
-
-   serial_out(early_serial_base, LCR, 0x3);/* 8n1 */
-   serial_out(early_serial_base, IER, 0);  /* no interrupt */
-   serial_out(early_serial_base, FCR, 0);  /* no fifo */
-   serial_out(early_serial_base, MCR, 0x3);/* DTR + RTS */
-
-   c = serial_in(early_serial_base, LCR);
-   serial_out(early_serial_base, LCR, c | DLAB);
-   serial_out(early_serial_base, DLL, divisor & 0xff);
-   serial_out(early_serial_base, DLH, (divisor >> 8) & 0xff);
-   serial_out(early_serial_base, LCR, c & ~DLAB);
-}
-
 #define DEFAULT_BAUD 9600
 
 static __init void early_serial_init(char *s)
 {
+   unsigned char c;
unsigned divisor;
-   unsigned long baud = DEFAULT_BAUD;
+   unsigned baud = DEFAULT_BAUD;
char *e;
 
if (*s == ',')
@@ -174,138 +145,23 @@ static __init void early_serial_init(char *s)
s++;
}
 
-   if (*s) {
-   if (kstrtoul(s, 0, &baud) < 0 || baud == 0)
-   baud = DEFAULT_BAUD;
-   }
-
-   /* Convert from baud to divisor value */
-   divisor = 115200 / baud;
-
-   /* These will always be IO based ports */
-   serial_in = io_serial_in;
-   serial_out = io_serial_out;
-
-   /* Set up the HW */
-   early_serial_hw_init(divisor);
-}
-
-#ifdef CONFIG_PCI
-static void mem32_serial_out(unsigned long addr, int offset, int value)
-{
-   u32 *vaddr = (u32 *)addr;
-   /* shift implied by pointer type */
-   writel(value, vaddr + offset);
-}
-
-static unsigned int mem32_serial_in(unsigned long addr, int offset)
-{
-   u32 *vaddr = (u32 *)addr;
-   /* shift implied by pointer type */
-   return readl(vaddr + offset);
-}
-
-/*
- * early_pci_serial_init()
- *
- * This function is invoked when the early_printk param starts with "pciserial"
- * The rest of the param should be ",B:D.F,baud" where B, D & F describe the
- * location of a PCI device that must be a UART device.
- */
-static __init void early_pci_serial_init(char *s)
-{
-   unsigned divisor;
-   unsigned long baud = DEFAULT_BAUD;
-   u8 bus, slot, func;
-   u32 classcode, bar0;
-   u16 cmdreg;
-   char *e;
-
-
-   /*
-* First, part the param to get the BDF values
-*/
-   if (*s == ',')
-   ++s;
-
-   if (*s == 0)
-   return;
-
-   bus = (u8)si

[PATCH v3 1/2] serial_core: add pci uart early console support

2015-05-18 Thread Bin Gao
On some Intel Atom SoCs, the legacy IO port UART(0x3F8) is not available.
Instead, a 8250 compatible PCI uart can be used as early console.
This patch adds pci support to the 8250 early console driver uart8250.
For example, to enable pci uart(00:21.3) as early console on these
platforms, append the following line to the kernel command line
(assume baud rate is 115200):
earlyprintk=uart8250,pci32,0:24.2,115200n8

Signed-off-by: Bin Gao 
---
 arch/x86/Kconfig |  11 +++
 drivers/tty/serial/earlycon.c|   9 +++
 drivers/tty/serial/serial_core.c | 145 ++-
 3 files changed, 163 insertions(+), 2 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 226d569..1283220 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2228,6 +2228,8 @@ config PCI
  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
  VESA. If you have PCI, say Y, otherwise N.
 
+   select HAVE_EARLY_PCI
+
 choice
prompt "PCI access mode"
depends on X86_32 && PCI
@@ -2265,6 +2267,15 @@ config PCI_GOANY
 
 endchoice
 
+config HAVE_EARLY_PCI
+   def_bool y
+   help
+ This option indicates that a group of APIs are available (in
+ asm/pci-direct.h) so the kernel can access pci config registers
+ before the PCI subsystem is initialized. Any arch that supports
+ early pci APIs must enable this option which is required  by arch
+ independent codes, e.g. uart8250 pci early console driver.
+
 config PCI_BIOS
def_bool y
depends on X86_32 && PCI && (PCI_GOBIOS || PCI_GOANY)
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index 6dc471e..63ae60e 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -193,6 +193,15 @@ static int __init param_setup_earlycon(char *buf)
 }
 early_param("earlycon", param_setup_earlycon);
 
+/* x86 uses "earlyprintk=xxx", so we keep the compatibility here */
+#ifdef CONFIG_X86
+static int __init param_setup_earlycon_x86(char *buf)
+{
+   return param_setup_earlycon(buf);
+}
+early_param("earlyprintk", param_setup_earlycon_x86);
+#endif
+
 int __init of_setup_earlycon(unsigned long addr,
 int (*setup)(struct earlycon_device *, const char 
*))
 {
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 0b7bb12..06218f5 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -34,10 +34,15 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
 
+#ifdef CONFIG_HAVE_EARLY_PCI
+#include 
+#endif
+
 /*
  * This is used to lock changes in serial line configuration.
  */
@@ -1808,6 +1813,110 @@ uart_get_console(struct uart_port *ports, int nr, 
struct console *co)
return ports + idx;
 }
 
+static int parse_bdf(char *options, char **endp, char delimiter, u8 *val)
+{
+   char str[4]; /* max 3 chars, plus a NULL terminator */
+   char *p = options;
+   int i = 0;
+
+   while (*p) {
+   if (i >= 4)
+   return -EINVAL;
+
+   if (*p == delimiter) {
+   str[i++] = 0;
+   if (endp)
+   *endp = p + 1;
+   return kstrtou8(str, 10, val); /* decimal, no hex */
+   }
+
+   str[i++] = *p++;
+   }
+
+   return -EINVAL;
+}
+
+#ifdef CONFIG_HAVE_EARLY_PCI
+/*
+ * The whole pci option from the command line is: pci[32],B:D.F[,options]
+ * Examples:
+ * pci,0:21.3,115200n8
+ * pci32,0:21.3
+ * Here pci32 means 8250 UART registers are 32-bit width(regshift = 2).
+ * pci means 8250 UART registers are 8-bit width(regshift = 0).
+ * B,D and F are bus, device and function, in decimal(not hex).
+ * The additional options(115200n8) would be parsed by the earlycon framework.
+ *
+ * @options: the pci options
+ * @phys: the pointer to return pci mem or io address
+ * return: <0: error
+ *  0: pci mem
+ *  1: pci io
+ */
+static int parse_pci_options(char *options, unsigned long *phys)
+{
+   u8 bus, dev, func;
+   char *endp;
+   u64 bar0;
+   u16 cmd;
+   int pci_io = 0;
+
+   if (!early_pci_allowed()) {
+   pr_err("earlycon pci not available(early pci not allowed)\n");
+   return -EINVAL;
+   }
+
+   /* We come here with options=B:D.F[,options] */
+   if (parse_bdf(options, &endp, ':', &bus))
+   goto failed;
+
+   if (parse_bdf(endp, &endp, '.', &dev))
+   goto failed;
+
+   if (parse_bdf(endp, &endp, ',', &func))
+   goto failed;
+
+   /*
+* On these platforms class code in pci config is broken,
+* so skip checking it.
+*/
+
+   bar0 = re

[PATCH v3 2/2] arch/x86: remove pci uart early console from early_prink.c

2015-05-18 Thread Bin Gao
The arch independent uart8250 early console driver has good
support for memory mapped and io port based 8250 uarts. Since
pci is arch independent so it's natural to extend uart8250 to
support mem, io and pci. Hence pci uart early console in
arch/x86/kernel_printk.c by the following commit:
'commit 5140fda16051 ("Specify PCI based UART for earlyprintk")'
is removed. And its equivalent function will be available from
uart8250 early console driver.

Signed-off-by: Bin Gao 
---
 arch/x86/kernel/early_printk.c | 180 -
 1 file changed, 15 insertions(+), 165 deletions(-)

diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index 89427d8..00c2e2a 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -19,7 +19,6 @@
 #include 
 #include 
 #include 
-#include 
 
 /* Simple VGA output */
 #define VGABASE(__ISA_IO_base + 0xb8000)
@@ -77,7 +76,7 @@ static struct console early_vga_console = {
 
 /* Serial functions loosely based on a similar package from Klaus P. Gerlicher 
*/
 
-static unsigned long early_serial_base = 0x3f8;  /* ttyS0 */
+static int early_serial_base = 0x3f8;  /* ttyS0 */
 
 #define XMTRDY  0x20
 
@@ -95,26 +94,13 @@ static unsigned long early_serial_base = 0x3f8;  /* ttyS0 */
 #define DLL 0   /*  Divisor Latch Low */
 #define DLH 1   /*  Divisor latch High*/
 
-static unsigned int io_serial_in(unsigned long addr, int offset)
-{
-   return inb(addr + offset);
-}
-
-static void io_serial_out(unsigned long addr, int offset, int value)
-{
-   outb(value, addr + offset);
-}
-
-static unsigned int (*serial_in)(unsigned long addr, int offset) = 
io_serial_in;
-static void (*serial_out)(unsigned long addr, int offset, int value) = 
io_serial_out;
-
 static int early_serial_putc(unsigned char ch)
 {
unsigned timeout = 0x;
 
-   while ((serial_in(early_serial_base, LSR) & XMTRDY) == 0 && --timeout)
+   while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
cpu_relax();
-   serial_out(early_serial_base, TXR, ch);
+   outb(ch, early_serial_base + TXR);
return timeout ? 0 : -1;
 }
 
@@ -128,28 +114,13 @@ static void early_serial_write(struct console *con, const 
char *s, unsigned n)
}
 }
 
-static __init void early_serial_hw_init(unsigned divisor)
-{
-   unsigned char c;
-
-   serial_out(early_serial_base, LCR, 0x3);/* 8n1 */
-   serial_out(early_serial_base, IER, 0);  /* no interrupt */
-   serial_out(early_serial_base, FCR, 0);  /* no fifo */
-   serial_out(early_serial_base, MCR, 0x3);/* DTR + RTS */
-
-   c = serial_in(early_serial_base, LCR);
-   serial_out(early_serial_base, LCR, c | DLAB);
-   serial_out(early_serial_base, DLL, divisor & 0xff);
-   serial_out(early_serial_base, DLH, (divisor >> 8) & 0xff);
-   serial_out(early_serial_base, LCR, c & ~DLAB);
-}
-
 #define DEFAULT_BAUD 9600
 
 static __init void early_serial_init(char *s)
 {
+   unsigned char c;
unsigned divisor;
-   unsigned long baud = DEFAULT_BAUD;
+   unsigned baud = DEFAULT_BAUD;
char *e;
 
if (*s == ',')
@@ -174,138 +145,23 @@ static __init void early_serial_init(char *s)
s++;
}
 
-   if (*s) {
-   if (kstrtoul(s, 0, &baud) < 0 || baud == 0)
-   baud = DEFAULT_BAUD;
-   }
-
-   /* Convert from baud to divisor value */
-   divisor = 115200 / baud;
-
-   /* These will always be IO based ports */
-   serial_in = io_serial_in;
-   serial_out = io_serial_out;
-
-   /* Set up the HW */
-   early_serial_hw_init(divisor);
-}
-
-#ifdef CONFIG_PCI
-static void mem32_serial_out(unsigned long addr, int offset, int value)
-{
-   u32 *vaddr = (u32 *)addr;
-   /* shift implied by pointer type */
-   writel(value, vaddr + offset);
-}
-
-static unsigned int mem32_serial_in(unsigned long addr, int offset)
-{
-   u32 *vaddr = (u32 *)addr;
-   /* shift implied by pointer type */
-   return readl(vaddr + offset);
-}
-
-/*
- * early_pci_serial_init()
- *
- * This function is invoked when the early_printk param starts with "pciserial"
- * The rest of the param should be ",B:D.F,baud" where B, D & F describe the
- * location of a PCI device that must be a UART device.
- */
-static __init void early_pci_serial_init(char *s)
-{
-   unsigned divisor;
-   unsigned long baud = DEFAULT_BAUD;
-   u8 bus, slot, func;
-   u32 classcode, bar0;
-   u16 cmdreg;
-   char *e;
-
-
-   /*
-* First, part the param to get the BDF values
-*/
-   if (*s == ',')
-   ++s;
-
-   if (*s == 0)
-   return;
-
-   bus = (u8)si

Re: [PATCH v3 1/2] serial_core: add pci uart early console support

2015-05-19 Thread Bin Gao
On Tue, May 19, 2015 at 02:01:07PM +0200, Paul Bolle wrote:
> On Mon, 2015-05-18 at 14:21 -0700, Bin Gao wrote:
> > --- a/arch/x86/Kconfig
> > +++ b/arch/x86/Kconfig
> > @@ -2228,6 +2228,8 @@ config PCI
> >   your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
> >   VESA. If you have PCI, say Y, otherwise N.
> >  
> > +   select HAVE_EARLY_PCI
> > +
> 
> It's legal to have options after the help text of a Kconfig entry. It's
> also very uncommon to do that. Please put this select statement before
> the line reading "---help---" of the PCI entry.
>  
Will fix this in next patch set.

> > +config HAVE_EARLY_PCI
> > +   def_bool y
> 
> You probably want just
>   bool
> 
> here. Because this symbol has no further dependencies, which means
> HAVE_EARLY_PCI will now always be set to 'y'. That, in turn, makes the
> select you added above pointless.
>
Yes, you're right. bool is better.

 
> > +   help
> > + This option indicates that a group of APIs are available (in
> > + asm/pci-direct.h) so the kernel can access pci config registers
> > + before the PCI subsystem is initialized. Any arch that supports
> 
> Is this expected to be used outside of X86?
Yes, drivers/tty/serial/serial_core.c is going to use it.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


serial_core: add pci uart early console support

2015-05-13 Thread Bin Gao
>From 8977941ac3d70425fa7ca5ef3ab6de6c28743f1f Mon Sep 17 00:00:00 2001
From: Bin Gao 
Date: Tue, 12 May 2015 16:40:27 -0700
Subject: [PATCH] serial_core: add pci uart early console support

On some Intel Atom SoCs, the legacy IO port UART(0x3F8) is not available.
Instead, a 8250 compatible PCI uart can be used as early console.
This patch adds pci support to the 8250 early console driver uart8250.
For example, to enable pci uart(00:21.3) as early console on these
platforms, append the following line to the kernel command line
(assume baud rate is 115200):
earlycon=uart8250,pci32,0:24.2,115200n8

Signed-off-by: Bin Gao 
---
 drivers/tty/serial/serial_core.c | 140 ++-
 1 file changed, 138 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 0b7bb12..221143c 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -34,10 +34,16 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
 
+/* Only x86 has early pci access APIs */
+#if defined(CONFIG_PCI) && defined(CONFIG_X86)
+#include 
+#endif
+
 /*
  * This is used to lock changes in serial line configuration.
  */
@@ -1808,6 +1814,98 @@ uart_get_console(struct uart_port *ports, int nr, struct 
console *co)
return ports + idx;
 }
 
+#if defined(CONFIG_PCI) && defined(CONFIG_X86)
+static int parse_bdf(char *options, char **endp, char delimiter, u8 *val)
+{
+   char str[4]; /* max 3 chars, plus a NULL terminator */
+   char *p = options;
+   int i = 0;
+
+   while (*p) {
+   if (i >= 4)
+   return -EINVAL;
+
+   if (*p == delimiter) {
+   str[i++] = 0;
+   if (endp)
+   *endp = p + 1;
+   return kstrtou8(str, 10, val); /* decimal, no hex */
+   }
+
+   str[i++] = *p++;
+   }
+
+   return -EINVAL;
+}
+
+/*
+ * The whole pci option from the command line is: pci[32],B:D.F[,options]
+ * Examples:
+ * pci,0:21.3,115200n8
+ * pci32,0:21.3
+ * Here pci32 means 8250 UART registers are 32-bit width(regshift = 2).
+ * pci means 8250 UART registers are 8-bit width(regshift = 0).
+ * B,D and F are bus, device and function, in decimal(not hex).
+ * The additional options(115200n8) would be parsed by the earlycon framework.
+ *
+ * @options: the pci options
+ * @phys: the pointer to return pci mem or io address
+ * return: <0: error
+ *  0: pci mem
+ *  1: pci io
+ */
+static int parse_pci_options(char *options, unsigned long *phys)
+{
+   u8 bus, dev, func;
+   char *endp;
+   u64 bar0;
+   u16 cmd;
+   int pci_io = 0;
+
+   /* We come here with options=B:D.F[,options] */
+   if (parse_bdf(options, &endp, ':', &bus))
+   goto failed;
+
+   if (parse_bdf(endp, &endp, '.', &dev))
+   goto failed;
+
+   if (parse_bdf(endp, &endp, ',', &func))
+   goto failed;
+
+   /*
+* On these platforms class code in pci config is broken,
+* so skip checking it.
+*/
+
+   bar0 = read_pci_config(bus, dev, func, PCI_BASE_ADDRESS_0);
+
+   /* The BAR is IO or Memory? */
+   if ((bar0 & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
+   pci_io = 1;
+
+   if ((bar0 & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+   PCI_BASE_ADDRESS_MEM_TYPE_64)
+   bar0 |= (u64)read_pci_config(bus, dev, func,
+   PCI_BASE_ADDRESS_0 + 4) << 32;
+
+   *phys = bar0 & (pci_io ? PCI_BASE_ADDRESS_IO_MASK :
+PCI_BASE_ADDRESS_MEM_MASK);
+
+   /* Enable address decoding */
+   cmd = read_pci_config_16(bus, dev, func, PCI_COMMAND);
+   write_pci_config_16(bus, dev, func, PCI_COMMAND,
+   cmd | (pci_io ? PCI_COMMAND_IO : PCI_COMMAND_MEMORY));
+
+   pr_info("Use 8250 uart at PCI :%02u:%02u.%01u as early console\n",
+   bus, dev, func);
+   return pci_io;
+
+failed:
+   pr_err("Invalid earlycon pci parameters\n");
+   return -EINVAL;
+}
+#endif
+
 /**
  * uart_parse_earlycon - Parse earlycon options
  * @p:   ptr to 2nd field (ie., just beyond ',')
@@ -1816,8 +1914,9 @@ uart_get_console(struct uart_port *ports, int nr, struct 
console *co)
  * @options: ptr for  field; NULL if not present (out)
  *
  * Decodes earlycon kernel command line parameters of the form
- *earlycon=,io|mmio|mmio32,,
+ *earlycon=,io|mmio|mmio32|pci|pci32,,
  *console=,io|mmio|mmio32,,
+ * For pci/pci32, the  format is B:D.F, e.g. 0:24.2
  *
  * The optional form
  *earlycon=,0x,
@@ -1829,12 +1928,27 @@

Re: [PATCH 1/2] usb: typec: Add USB Power Delivery sink port support

2016-07-15 Thread Bin Gao
On Fri, Jul 15, 2016 at 08:31:08AM +0200, Oliver Neukum wrote:
> > +static void ack_message(struct pd_sink_port *port, int msg_id)
> > +{
> > +   struct pd_msg_header *header = kzalloc(PD_MSG_HEADER_LEN, GFP_KERNEL);
> 
> This must be GFP_NOIO. We are in a cycle that can lead to deadlock.
> 
> Assume we are waiting for a request for more power to process IO
> which we need to ack.
> 
> 1. memory allocation leads to laundering, blocks on freeing memory
> 2. launderer decides to perform IO which needs more power
> 3. more power has already been requested, wait for it to be granted
> 
> 4. BANG - DEADLOCK
Agree, I'll change the GFP flag in next revision.

> > +   struct pd_msg_header *header = kzalloc(PD_MSG_HEADER_LEN +
> > +   port->nr_ps * PD_OBJ_SIZE, GFP_KERNEL);
> 
> Must be GFP_NOIO. For the same reason as above. We may be asked
> this to resolve a mismatch due to needing more power for IO.
Yes will do.

> > +static void handle_soft_reset(struct pd_sink_port *port)
> > +{
> > +   struct pd_msg_header *header = kzalloc(PD_MSG_HEADER_LEN, GFP_KERNEL);
> > +
> > +   if (!header)
> > +   return;
> > +
> > +   flush_workqueue(port->rx_wq);
> 
> That is problematic. We may be here precisely because something is wrong
> blocking progress. In particular what happens if another soft reset
> is queued?
I'm going to remove the workqueue.

> > +   struct pd_msg_header *header = kzalloc(PD_MSG_HEADER_LEN +
> > +   PD_OBJ_SIZE, GFP_KERNEL);
> 
> GFP_NOIO, same reasons
Yes.

> > +
> 
>   HTH
>   Oliver
Thanks for your review.


Re: [PATCH 1/2] usb: typec: Add USB Power Delivery sink port support

2016-07-15 Thread Bin Gao
On Fri, Jul 15, 2016 at 02:21:48PM +0300, Felipe Balbi wrote:
> Greg Kroah-Hartman  writes:
> > On Fri, Jul 15, 2016 at 01:38:12PM +0300, Felipe Balbi wrote:
> >> 
> >> Hi,
> >> 
> >> Bin Gao  writes:
> >> > +static void print_message(int port, bool is_cmsg, u8 msg, bool recv)
> >> > +{
> >> > +pr_info("sink port %d: %s message %s %s\n", port,
> >> > +is_cmsg ? "Control" : "Data",
> >> > +msg_to_string(is_cmsg, msg),
> >> > + recv ? "received" : "sent(wait GOODCRC)");
> >> > +}
> >> 
> >> this is problematic. By default, we're all using 115200 8N1 baud
> >> rate. This message alone prints anywhere from 50 to 100 characters (I
> >> didn't really count properly, these are rough numbers), and that takes:
> >> 
> >> n50chars_time = 50 / (115200 / 10) = 4.3ms
> >> n100chars_time = 100 / (115200 / 10) = 8.6ms
> >> 
> >> Considering you have 30ms to reply with Power Request after GoodCRC, and
> >> considering you're printing several of these messages, they become
> >> really expensive and eat up valuable time from tSenderReply.
> >
> > printk() should be async, so it shouldn't be that big of a deal.
> 
> I can actually see this causing problems ;-) With this pr_info(),
> sometimes tSenderReply times out and Source gives a HardReset. Without
> pr_info(), type-c analyzer tells me we reply in less than 1ms.
> 
> > What is wrong is that this isn't using dev_info().
> 
> right, that too.
> 
> -- 
> balbi

When we don't have a struct device pointer for this driver,
a dev_info(NULL, fmt, ...) is equivalent to pr_info(). So we have to
use dev_info() here?
But I agree at least it should be pr_debug().


Re: [PATCH 1/2] usb: typec: Add USB Power Delivery sink port support

2016-07-15 Thread Bin Gao
On Fri, Jul 15, 2016 at 10:25:36AM +0300, Felipe Balbi wrote:
> Bin Gao  writes:
> 
> > This patch implements a simple USB Power Delivery sink port state machine.
> > It assumes the hardware only handles PD packet transmitting and receiving
> > over the CC line of the USB Type-C connector. The state transition is
> > completely controlled by software. This patch only implement the sink port
> > function and it doesn't support source port and port swap yet.
> >
> > This patch depends on these two patches:
> > https://lkml.org/lkml/2016/6/29/349
> > https://lkml.org/lkml/2016/6/29/350
> >
> > Signed-off-by: Bin Gao 
> > ---
> >  drivers/usb/typec/Kconfig  |  13 +
> >  drivers/usb/typec/Makefile |   1 +
> >  drivers/usb/typec/pd_sink.c| 967 
> > +
> >  include/linux/usb/pd_message.h | 371 
> >  include/linux/usb/pd_sink.h| 286 
> >  5 files changed, 1638 insertions(+)
> >  create mode 100644 drivers/usb/typec/pd_sink.c
> >  create mode 100644 include/linux/usb/pd_message.h
> >  create mode 100644 include/linux/usb/pd_sink.h
> >
> > diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig
> > index 7a345a4..a04a900 100644
> > --- a/drivers/usb/typec/Kconfig
> > +++ b/drivers/usb/typec/Kconfig
> > @@ -4,12 +4,25 @@ menu "USB PD and Type-C drivers"
> >  config TYPEC
> > tristate
> >  
> > +config USB_PD_SINK
> > +   bool "USB Power Delivery Sink Port State Machine Driver"
> 
> tristate?
> 
> > +   select TYPEC
> 
> this should depend on TYPEC, not select it.
> 
> > +   help
> > + Enable this to support USB PD(Power Delivery) Sink port.
> > + This driver implements a simple USB PD sink state machine.
> > + The underlying TypeC phy driver is responsible for cable
> > + plug/unplug event, port orientation detection, transmitting
> > + and receiving PD messages. This driver only process messages
> > + received by the TypeC phy driver and maintain the sink port's
> > + state machine.
> > +
> >  config TYPEC_WCOVE
> > tristate "Intel WhiskeyCove PMIC USB Type-C PHY driver"
> > depends on ACPI
> > depends on INTEL_SOC_PMIC
> > depends on INTEL_PMC_IPC
> > select TYPEC
> > +   select USB_PD_SINK
> 
> TYPEC without PD is valid, let user select PD support.
Yes will fix the Kconfig in next revision.

> > +static void print_message(int port, bool is_cmsg, u8 msg, bool recv)
> > +{
> > +   pr_info("sink port %d: %s message %s %s\n", port,
> > +   is_cmsg ? "Control" : "Data",
> > +   msg_to_string(is_cmsg, msg),
> > +recv ? "received" : "sent(wait GOODCRC)");
> 
> looks like a debugging message to me. We don't want to spam dmesg with
> every single message transmission.
This should be a pr_debug().

> 
> > +static void start_timer(struct pd_sink_port *port, int timeout,
> > +   enum hrtimer_restart (*f)(struct hrtimer *))
> > +{
> > +   if (hrtimer_active(&port->tx_timer)) {
> > +   pr_err("Error: previous timer is still active\n");
> > +   return;
> > +   }
> > +
> > +   port->tx_timer.function = f;
> > +   /* timeout comes with ms but ktime_set takes seconds and nanoseconds */
> > +   hrtimer_start(&port->tx_timer, ktime_set(timeout / 1000,
> 
> I don't think you need HR timers here. A normal mod_timer() should do.
When hrtimer is in place, the old timer becomes "legacy". And the old timer
APIs are implemented on top of hrtimer. It's no harm to use hrtimers anywhere
in the kernel and it would be encouraged in my opinion:-)

> 
> > +static enum hrtimer_restart goodcrc_timeout(struct hrtimer *timer)
> > +{
> > +   pr_err("GOODCRC message is not received in %d ms: timeout\n",
> > +   PD_TIMEOUT_GOODCRC);
> > +   return HRTIMER_NORESTART;
> > +}
> > +
> > +/*
> > + * For any message we send, we must get a GOODCRC message from the Source.
> > + * The USB PD spec says the time should be measured between the last bit
> > + * of the sending message's EOP has been transmitted and the last bit of
> > + * the receiving GOODCRC message's EOP has been received. The allowed time
> > + * is minimal 0.9 ms and maximal 1.1 ms. However, this measurement is
> > + * performed in physical la

Re: [PATCH 1/2] usb: typec: Add USB Power Delivery sink port support

2016-07-18 Thread Bin Gao
On Sat, Jul 16, 2016 at 08:49:53AM +0900, Greg Kroah-Hartman wrote:
> On Fri, Jul 15, 2016 at 03:41:10PM -0700, Bin Gao wrote:
> > On Fri, Jul 15, 2016 at 02:21:48PM +0300, Felipe Balbi wrote:
> > > Greg Kroah-Hartman  writes:
> > > > On Fri, Jul 15, 2016 at 01:38:12PM +0300, Felipe Balbi wrote:
> > > >> 
> > > >> Hi,
> > > >> 
> > > >> Bin Gao  writes:
> > > >> > +static void print_message(int port, bool is_cmsg, u8 msg, bool recv)
> > > >> > +{
> > > >> > +pr_info("sink port %d: %s message %s %s\n", port,
> > > >> > +is_cmsg ? "Control" : "Data",
> > > >> > +msg_to_string(is_cmsg, msg),
> > > >> > + recv ? "received" : "sent(wait GOODCRC)");
> > > >> > +}
> > > >> 
> > > >> this is problematic. By default, we're all using 115200 8N1 baud
> > > >> rate. This message alone prints anywhere from 50 to 100 characters (I
> > > >> didn't really count properly, these are rough numbers), and that takes:
> > > >> 
> > > >> n50chars_time = 50 / (115200 / 10) = 4.3ms
> > > >> n100chars_time = 100 / (115200 / 10) = 8.6ms
> > > >> 
> > > >> Considering you have 30ms to reply with Power Request after GoodCRC, 
> > > >> and
> > > >> considering you're printing several of these messages, they become
> > > >> really expensive and eat up valuable time from tSenderReply.
> > > >
> > > > printk() should be async, so it shouldn't be that big of a deal.
> > > 
> > > I can actually see this causing problems ;-) With this pr_info(),
> > > sometimes tSenderReply times out and Source gives a HardReset. Without
> > > pr_info(), type-c analyzer tells me we reply in less than 1ms.
> > > 
> > > > What is wrong is that this isn't using dev_info().
> > > 
> > > right, that too.
> > > 
> > > -- 
> > > balbi
> > 
> > When we don't have a struct device pointer for this driver,
> 
> Then you should fix that, as this is a driver for hardware :)
This is actualy a software stack to implement the USB PD spec.
Only the USB Type-C phy driver has a device pointer.
The PD stack vs. USB Type-C phy driver is similar to TCP/IP stack
vs. ethernet driver in the kernel. We don't have a device pointer
for TCP/IP stack code either.

Thanks,
Bin

> 
> thanks,
> 
> greg k-h


Re: [PATCH 1/2] usb: typec: Add USB Power Delivery sink port support

2016-07-18 Thread Bin Gao
On Mon, Jul 18, 2016 at 10:07:24AM +0300, Felipe Balbi wrote:
> 
> Hi,
> 
> Bin Gao  writes:
> >> > +int pd_sink_queue_msg(struct pd_sink_msg *msg)
> >> > +{
> >> > +unsigned long flags;
> >> > +struct pd_sink_port *port;
> >> > +
> >> > +if (msg->port < 0 || msg->port >= MAX_NR_SINK_PORTS) {
> >> > +pr_err("Invalid port number\n");
> >> > +return -EINVAL;
> >> > +}
> >> > +
> >> > +port = sink_ports[msg->port];
> >> > +
> >> > +spin_lock_irqsave(&port->rx_lock, flags);
> >> > +list_add_tail(&msg->list, &port->rx_list);
> >> > +spin_unlock_irqrestore(&port->rx_lock, flags);
> >> > +
> >> > +queue_work(port->rx_wq, &port->rx_work);
> >> 
> >> can we really queue several messages at a time? It seems unfeasible to
> >> me. It's not like we can queue several power request in a role. Why do
> >> you need this workqueue? Why don't you process message here, in place?
> > Some Type-C chargers send two messages in a short duration(less than 1 ms),
> > e.g. a SOURCE_CAPABILITY follows the previous SOURCE_CAPABILITY, or a
> > GET_SINK_CAPABILITY follows a previous SOURCE_CAPABILITY, etc. Queuing
> > message to PD stack by Type-C phy driver typically happens in a interrupt
> > context. So in this case a nested interrupt may happen. Our whole PD
> > stack while processing one message is not re-entrant so the nested
> > interrupt would cause a problem.
> 
> keep interrupts masked for as long as necessary until your message is
> processed.

Yes, that's a right way to go. 
We'll have to document this because there might be other Type-C
PHY drivers(other than Intel Whiskey Cove PMIC) to use the PD stack.

> 
> -- 
> balbi




[PATCH v3] mfd: intel_soc_pmic_bxtwc: Add Intel BXT WhiskeyCove PMIC ADC thermal channel mapping and USB type-C resources

2016-06-23 Thread Bin Gao
This patch adds the mapping of PMIC ADC channel to thermal zone and
USB type-C resources. This mapping is used in the pmic thermal driver
to notify the thermal zone with the pmic adc channel alert interrupts.
This patch also adds three new data structures to
include/linux/mfd/intel_soc_pmic.h: struct trip_config_map{},
struct thermal_irq_map {} and struct pmic_thermal_data {} which are
required by changes we did on intel_soc_pmic_bxtwc.c.

Signed-off-by: Yegnesh S Iyer 
Signed-off-by: Rohit S Kenchanpura 
Signed-off-by: Bin Gao 
---
Changes in v3:
 - Added USB type-C resources.
Changes in v2:
 - Fixed subject line.
 - Combined two patches into one.
 drivers/mfd/intel_soc_pmic_bxtwc.c | 120 +
 include/linux/mfd/intel_soc_pmic.h |  21 +++
 2 files changed, 141 insertions(+)

diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c 
b/drivers/mfd/intel_soc_pmic_bxtwc.c
index b942876..9eacaf2 100644
--- a/drivers/mfd/intel_soc_pmic_bxtwc.c
+++ b/drivers/mfd/intel_soc_pmic_bxtwc.c
@@ -58,6 +58,10 @@
 #define BXTWC_MGPIO1IRQ0x4E1A
 #define BXTWC_MCRITIRQ 0x4E1B
 
+#define BXTWC_STHRM0IRQ0x4F19
+#define BXTWC_STHRM1IRQ0x4F1A
+#define BXTWC_STHRM2IRQ0x4F1B
+
 /* Whiskey Cove PMIC share same ACPI ID between different platforms */
 #define BROXTON_PMIC_WC_HRV4
 
@@ -84,6 +88,7 @@ enum bxtwc_irqs_level2 {
BXTWC_THRM2_IRQ,
BXTWC_BCU_IRQ,
BXTWC_ADC_IRQ,
+   BXTWC_USBC_IRQ,
BXTWC_CHGR0_IRQ,
BXTWC_CHGR1_IRQ,
BXTWC_GPIO0_IRQ,
@@ -110,12 +115,116 @@ static const struct regmap_irq 
bxtwc_regmap_irqs_level2[] = {
REGMAP_IRQ_REG(BXTWC_BCU_IRQ, 3, 0x1f),
REGMAP_IRQ_REG(BXTWC_ADC_IRQ, 4, 0xff),
REGMAP_IRQ_REG(BXTWC_CHGR0_IRQ, 5, 0x1f),
+   REGMAP_IRQ_REG(BXTWC_USBC_IRQ, 5, BIT(5)),
REGMAP_IRQ_REG(BXTWC_CHGR1_IRQ, 6, 0x1f),
REGMAP_IRQ_REG(BXTWC_GPIO0_IRQ, 7, 0xff),
REGMAP_IRQ_REG(BXTWC_GPIO1_IRQ, 8, 0x3f),
REGMAP_IRQ_REG(BXTWC_CRIT_IRQ, 9, 0x03),
 };
 
+static struct trip_config_map str0_trip_config[] = {
+   {
+   .irq_reg = BXTWC_THRM0IRQ,
+   .irq_mask = 0x01,
+   .irq_en = BXTWC_MTHRM0IRQ,
+   .irq_en_mask = 0x01,
+   .evt_stat = BXTWC_STHRM0IRQ,
+   .evt_mask = 0x01,
+   .trip_num = 0
+   },
+   {
+   .irq_reg = BXTWC_THRM0IRQ,
+   .irq_mask = 0x10,
+   .irq_en = BXTWC_MTHRM0IRQ,
+   .irq_en_mask = 0x10,
+   .evt_stat = BXTWC_STHRM0IRQ,
+   .evt_mask = 0x10,
+   .trip_num = 1
+   }
+};
+
+static struct trip_config_map str1_trip_config[] = {
+   {
+   .irq_reg = BXTWC_THRM0IRQ,
+   .irq_mask = 0x02,
+   .irq_en = BXTWC_MTHRM0IRQ,
+   .irq_en_mask = 0x02,
+   .evt_stat = BXTWC_STHRM0IRQ,
+   .evt_mask = 0x02,
+   .trip_num = 0
+   },
+   {
+   .irq_reg = BXTWC_THRM0IRQ,
+   .irq_mask = 0x20,
+   .irq_en = BXTWC_MTHRM0IRQ,
+   .irq_en_mask = 0x20,
+   .evt_stat = BXTWC_STHRM0IRQ,
+   .evt_mask = 0x20,
+   .trip_num = 1
+   },
+};
+
+static struct trip_config_map str2_trip_config[] = {
+   {
+   .irq_reg = BXTWC_THRM0IRQ,
+   .irq_mask = 0x04,
+   .irq_en = BXTWC_MTHRM0IRQ,
+   .irq_en_mask = 0x04,
+   .evt_stat = BXTWC_STHRM0IRQ,
+   .evt_mask = 0x04,
+   .trip_num = 0
+   },
+   {
+   .irq_reg = BXTWC_THRM0IRQ,
+   .irq_mask = 0x40,
+   .irq_en = BXTWC_MTHRM0IRQ,
+   .irq_en_mask = 0x40,
+   .evt_stat = BXTWC_STHRM0IRQ,
+   .evt_mask = 0x40,
+   .trip_num = 1
+   },
+};
+
+static struct trip_config_map str3_trip_config[] = {
+   {
+   .irq_reg = BXTWC_THRM2IRQ,
+   .irq_mask = 0x10,
+   .irq_en = BXTWC_MTHRM2IRQ,
+   .irq_en_mask = 0x10,
+   .evt_stat = BXTWC_STHRM2IRQ,
+   .evt_mask = 0x10,
+   .trip_num = 0
+   },
+};
+
+static struct thermal_irq_map bxtwc_thermal_irq_map[] = {
+   {
+   .handle = "STR0",
+   .trip_config = str0_trip_config,
+   .num_trips = ARRAY_SIZE(str0_trip_config),
+   },
+   {
+   .handle = "STR1",
+   .trip_config = str1_trip_config,
+   .num_trips = ARRAY_SIZE(str1_trip_config),
+   },
+   {
+   .handle = "STR2",
+   .trip_config = str2_trip_config,
+   .num_trips = ARRAY_SIZE(str2_trip_config),
+   },
+   {
+   .handle = "STR3",
+   .trip_config = str3

[PATCH v3 0/3] acpi/pmic: add opregion driver for Intel BXT WhiskeyCove PMIC

2016-06-23 Thread Bin Gao
This series modifies the pen function signature to take bit field
and adds a new opregion driver for Intel BXT WhiskeyCove PMIC. It
also adds support for PMIC regs operation region.

Yegnesh Iyer (1):
  acpi: pmic: Modifying the pen function signature to take bit field

Ajay Thomas (1):
  acpi: pmic: Add opregion driver for Intel BXT WhiskeyCove PMIC

Chandra Sekhar Anagani (1):
 acpi: pmic: Add support for PMIC regs operation region

 drivers/acpi/pmic/intel_pmic.c   | 87  +++--
 drivers/acpi/pmic/intel_pmic.h   | 11  ++--
 drivers/acpi/pmic/intel_pmic_crc.c   |  5  +++--
 drivers/acpi/Kconfig |  6  +
 drivers/acpi/Makefile|  1  +
 drivers/acpi/pmic/intel_pmic_bxtwc.c |449  +++
 6 files changed, 559 insertions(+), 10 deletions(-)
 create mode 100644 drivers/acpi/pmic/intel_pmic_bxtwc.c
--
1.9.1



[PATCH v3 1/3] acpi/pmic: modify the pen function signature to take bit field

2016-06-23 Thread Bin Gao
Issue description: On some pmics, the policy enable for thermal alerts
refers to different bit fields of the same registers, whereas on other
pmics, the policy enable refers to the same bit field on different
registers. Previous implementation did not provide the flexibility for
supporting the first approach.

Solution: Modified the policy enable function to take bit field as well.
The use of bit field is left to the pmic specific opregion driver.

Signed-off-by: Yegnesh Iyer 
Signed-off-by: Bin Gao 
---
Changes in v3: no change
Changes in v2:
 - Fixed subject line.
 drivers/acpi/pmic/intel_pmic.c | 13 +++--
 drivers/acpi/pmic/intel_pmic.h |  4 ++--
 drivers/acpi/pmic/intel_pmic_crc.c |  5 +++--
 3 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/drivers/acpi/pmic/intel_pmic.c b/drivers/acpi/pmic/intel_pmic.c
index bd772cd..410e96f 100644
--- a/drivers/acpi/pmic/intel_pmic.c
+++ b/drivers/acpi/pmic/intel_pmic.c
@@ -131,7 +131,7 @@ static int pmic_thermal_aux(struct intel_pmic_opregion 
*opregion, int reg,
 }
 
 static int pmic_thermal_pen(struct intel_pmic_opregion *opregion, int reg,
-   u32 function, u64 *value)
+   int bit, u32 function, u64 *value)
 {
struct intel_pmic_opregion_data *d = opregion->data;
struct regmap *regmap = opregion->regmap;
@@ -140,12 +140,12 @@ static int pmic_thermal_pen(struct intel_pmic_opregion 
*opregion, int reg,
return -ENXIO;
 
if (function == ACPI_READ)
-   return d->get_policy(regmap, reg, value);
+   return d->get_policy(regmap, reg, bit, value);
 
if (*value != 0 && *value != 1)
return -EINVAL;
 
-   return d->update_policy(regmap, reg, *value);
+   return d->update_policy(regmap, reg, bit, *value);
 }
 
 static bool pmic_thermal_is_temp(int address)
@@ -170,13 +170,13 @@ static acpi_status intel_pmic_thermal_handler(u32 
function,
 {
struct intel_pmic_opregion *opregion = region_context;
struct intel_pmic_opregion_data *d = opregion->data;
-   int reg, result;
+   int reg, bit, result;
 
if (bits != 32 || !value64)
return AE_BAD_PARAMETER;
 
result = pmic_get_reg_bit(address, d->thermal_table,
- d->thermal_table_count, ®, NULL);
+ d->thermal_table_count, ®, &bit);
if (result == -ENOENT)
return AE_BAD_PARAMETER;
 
@@ -187,7 +187,8 @@ static acpi_status intel_pmic_thermal_handler(u32 function,
else if (pmic_thermal_is_aux(address))
result = pmic_thermal_aux(opregion, reg, function, value64);
else if (pmic_thermal_is_pen(address))
-   result = pmic_thermal_pen(opregion, reg, function, value64);
+   result = pmic_thermal_pen(opregion, reg, bit,
+   function, value64);
else
result = -EINVAL;
 
diff --git a/drivers/acpi/pmic/intel_pmic.h b/drivers/acpi/pmic/intel_pmic.h
index d4e90af..e8bfa7b 100644
--- a/drivers/acpi/pmic/intel_pmic.h
+++ b/drivers/acpi/pmic/intel_pmic.h
@@ -12,8 +12,8 @@ struct intel_pmic_opregion_data {
int (*update_power)(struct regmap *r, int reg, int bit, bool on);
int (*get_raw_temp)(struct regmap *r, int reg);
int (*update_aux)(struct regmap *r, int reg, int raw_temp);
-   int (*get_policy)(struct regmap *r, int reg, u64 *value);
-   int (*update_policy)(struct regmap *r, int reg, int enable);
+   int (*get_policy)(struct regmap *r, int reg, int bit, u64 *value);
+   int (*update_policy)(struct regmap *r, int reg, int bit, int enable);
struct pmic_table *power_table;
int power_table_count;
struct pmic_table *thermal_table;
diff --git a/drivers/acpi/pmic/intel_pmic_crc.c 
b/drivers/acpi/pmic/intel_pmic_crc.c
index fcd1852..d7f1761 100644
--- a/drivers/acpi/pmic/intel_pmic_crc.c
+++ b/drivers/acpi/pmic/intel_pmic_crc.c
@@ -141,7 +141,8 @@ static int intel_crc_pmic_update_aux(struct regmap *regmap, 
int reg, int raw)
regmap_update_bits(regmap, reg - 1, 0x3, raw >> 8) ? -EIO : 0;
 }
 
-static int intel_crc_pmic_get_policy(struct regmap *regmap, int reg, u64 
*value)
+static int intel_crc_pmic_get_policy(struct regmap *regmap,
+   int reg, int bit, u64 *value)
 {
int pen;
 
@@ -152,7 +153,7 @@ static int intel_crc_pmic_get_policy(struct regmap *regmap, 
int reg, u64 *value)
 }
 
 static int intel_crc_pmic_update_policy(struct regmap *regmap,
-   int reg, int enable)
+   int reg, int bit, int enable)
 {
int alert0;
 
-- 
1.9.1



[PATCH v3 2/3] acpi/pmic: Add opregion driver for Intel BXT WhiskeyCove PMIC

2016-06-23 Thread Bin Gao
This patch adds operation region driver for Intel BXT WhiskeyCove
PMIC. The register mapping is done as per the BXT WC data sheet.

Signed-off-by: Ajay Thomas 
Signed-off-by: Felipe Balbi 
Signed-off-by: Chandra Sekhar Anagani 
Signed-off-by: Bin Gao 
---
Changes in v3:
 - Added regs_read() and regs_write() methods to the
   intel_pmic_opregion_data{} structure.
Changs in v2:
 - Replaced module_init() with device_initcall().
 drivers/acpi/Kconfig |   6 +
 drivers/acpi/Makefile|   1 +
 drivers/acpi/pmic/intel_pmic.h   |   2 +
 drivers/acpi/pmic/intel_pmic_bxtwc.c | 449 +++
 4 files changed, 458 insertions(+)
 create mode 100644 drivers/acpi/pmic/intel_pmic_bxtwc.c

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index b7e2e77..47cb6f6 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -519,6 +519,12 @@ config XPOWER_PMIC_OPREGION
help
  This config adds ACPI operation region support for XPower AXP288 PMIC.
 
+config BXT_WC_PMIC_OPREGION
+   bool "ACPI operation region support for BXT WhiskeyCove PMIC"
+   depends on INTEL_SOC_PMIC
+   help
+ This config adds ACPI operation region support for BXT WhiskeyCove 
PMIC.
+
 endif
 
 endif  # ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 251ce85..5da9d4b 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -99,5 +99,6 @@ obj-$(CONFIG_ACPI_EXTLOG) += acpi_extlog.o
 obj-$(CONFIG_PMIC_OPREGION)+= pmic/intel_pmic.o
 obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o
 obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o
+obj-$(CONFIG_BXT_WC_PMIC_OPREGION) += pmic/intel_pmic_bxtwc.o
 
 video-objs += acpi_video.o video_detect.o
diff --git a/drivers/acpi/pmic/intel_pmic.h b/drivers/acpi/pmic/intel_pmic.h
index e8bfa7b..2f39ee0 100644
--- a/drivers/acpi/pmic/intel_pmic.h
+++ b/drivers/acpi/pmic/intel_pmic.h
@@ -12,6 +12,8 @@ struct intel_pmic_opregion_data {
int (*update_power)(struct regmap *r, int reg, int bit, bool on);
int (*get_raw_temp)(struct regmap *r, int reg);
int (*update_aux)(struct regmap *r, int reg, int raw_temp);
+   int (*regs_read)(struct regmap *r, u16 address, unsigned int *value);
+   int (*regs_write)(struct regmap *r, u16 address, unsigned int value);
int (*get_policy)(struct regmap *r, int reg, int bit, u64 *value);
int (*update_policy)(struct regmap *r, int reg, int bit, int enable);
struct pmic_table *power_table;
diff --git a/drivers/acpi/pmic/intel_pmic_bxtwc.c 
b/drivers/acpi/pmic/intel_pmic_bxtwc.c
new file mode 100644
index 000..51d5bcc
--- /dev/null
+++ b/drivers/acpi/pmic/intel_pmic_bxtwc.c
@@ -0,0 +1,449 @@
+/*
+ * intel_pmic_bxtwc.c - Intel BXT WhiskeyCove PMIC operation region driver
+ *
+ * Copyright (C) 2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "intel_pmic.h"
+
+#define WHISKEY_COVE_ALRT_HIGH_BIT_MASK 0x0F
+#define WHISKEY_COVE_ADC_HIGH_BIT(x)   (((x & 0x0F) << 8))
+#define WHISKEY_COVE_ADC_CURSRC(x) (((x & 0xF0) >> 4))
+#define VR_MODE_DISABLED0
+#define VR_MODE_AUTOBIT(0)
+#define VR_MODE_NORMAL  BIT(1)
+#define VR_MODE_SWITCH  BIT(2)
+#define VR_MODE_ECO (BIT(0)|BIT(1))
+#define VSWITCH2_OUTPUT BIT(5)
+#define VSWITCH1_OUTPUT BIT(4)
+#define VUSBPHY_CHARGE  BIT(1)
+
+static struct pmic_table power_table[] = {
+   {
+   .address = 0x0,
+   .reg = 0x63,
+   .bit = VR_MODE_AUTO,
+   }, /* VDD1 -> VDD1CNT */
+   {
+   .address = 0x04,
+   .reg = 0x65,
+   .bit = VR_MODE_AUTO,
+   }, /* VDD2 -> VDD2CNT */
+   {
+   .address = 0x08,
+   .reg = 0x67,
+   .bit = VR_MODE_AUTO,
+   }, /* VDD3 -> VDD3CNT */
+   {
+   .address = 0x0c,
+   .reg = 0x6d,
+   .bit = VR_MODE_AUTO,
+   }, /* VLFX -> VFLEXCNT */
+   {
+   .address = 0x10,
+   .reg = 0x6f,
+   .bit = VR_MODE_NORMAL,
+   }, /* VP1A -> VPROG1ACNT */
+   {
+   .address = 0x14,
+   .reg = 0x70,
+   .bit = VR_MODE_NORMAL,
+   }, /* VP1B -> VPROG1BCNT */
+   {
+   .address = 0x18,
+   .reg = 0x71,

[PATCH v3 3/3] acpi/pmic: Add support for PMIC regs operation region

2016-06-23 Thread Bin Gao
Broxton platform firmware has defined new customized operation
regions called regs for PMIC chip which is used to handle the
PMIC gpio mainly intended for the TYPE-C VBUS and Orientation.

The intel_pmic_regs structure is created also for this purpose
of handling the PMIC register read and write.

Signed-off-by: Chandra Sekhar Anagani 
Signed-off-by: Felipe Balbi 
Signed-off-by: Bin Gao 
---
Changes in v3: none
Changes in v2: none
 drivers/acpi/pmic/intel_pmic.c | 74 +-
 drivers/acpi/pmic/intel_pmic.h |  5 +++
 2 files changed, 71 insertions(+), 8 deletions(-)

diff --git a/drivers/acpi/pmic/intel_pmic.c b/drivers/acpi/pmic/intel_pmic.c
index 410e96f..53b7052 100644
--- a/drivers/acpi/pmic/intel_pmic.c
+++ b/drivers/acpi/pmic/intel_pmic.c
@@ -21,12 +21,14 @@
 
 #define PMIC_POWER_OPREGION_ID 0x8d
 #define PMIC_THERMAL_OPREGION_ID   0x8c
+#define PMIC_REGS_OPREGION_ID  0x8f
 
 struct intel_pmic_opregion {
struct mutex lock;
struct acpi_lpat_conversion_table *lpat_table;
struct regmap *regmap;
struct intel_pmic_opregion_data *data;
+   struct pmic_regs_handlerctx;
 };
 
 static int pmic_get_reg_bit(int address, struct pmic_table *table,
@@ -204,6 +206,52 @@ static acpi_status intel_pmic_thermal_handler(u32 function,
return AE_OK;
 }
 
+static acpi_status intel_pmic_regs_handler(u32 function,
+   acpi_physical_address address, u32 bits, u64 *value64,
+   void *handler_context, void *region_context)
+{
+   struct intel_pmic_opregion *opregion = region_context;
+   struct intel_pmic_opregion_data *d = opregion->data;
+   int result = 0;
+
+   switch (address) {
+   case 0:
+   return AE_OK;
+   case 1:
+   opregion->ctx.address |= (*value64 & 0xff) << 8;
+   return AE_OK;
+   case 2:
+   opregion->ctx.address |= *value64 & 0xff;
+   return AE_OK;
+   case 3:
+   opregion->ctx.value = *value64 & 0xff;
+   return AE_OK;
+   case 4:
+   if (*value64) {
+   result = d->regs_write(opregion->regmap,
+   opregion->ctx.address,
+   opregion->ctx.value);
+   } else {
+   result = d->regs_read(opregion->regmap,
+   opregion->ctx.address,
+   &opregion->ctx.value);
+   if (result == 0)
+   *value64 = opregion->ctx.value;
+   }
+   memset(&opregion->ctx, 0x00, sizeof(opregion->ctx));
+   }
+
+   if (result < 0) {
+   if (result == -EINVAL)
+   return AE_BAD_PARAMETER;
+   else
+   return AE_ERROR;
+   }
+
+   return AE_OK;
+}
+
+
 int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
struct regmap *regmap,
struct intel_pmic_opregion_data *d)
@@ -227,21 +275,31 @@ int intel_pmic_install_opregion_handler(struct device 
*dev, acpi_handle handle,
opregion->lpat_table = acpi_lpat_get_conversion_table(handle);
 
status = acpi_install_address_space_handler(handle,
-   PMIC_POWER_OPREGION_ID,
-   intel_pmic_power_handler,
-   NULL, opregion);
+   PMIC_POWER_OPREGION_ID,
+   intel_pmic_power_handler,
+   NULL, opregion);
+   if (ACPI_FAILURE(status)) {
+   ret = -ENODEV;
+   goto out_error;
+   }
+
+   status = acpi_install_address_space_handler(handle,
+   PMIC_THERMAL_OPREGION_ID,
+   intel_pmic_thermal_handler,
+   NULL, opregion);
if (ACPI_FAILURE(status)) {
+   acpi_remove_address_space_handler(handle,
+   PMIC_POWER_OPREGION_ID,
+   intel_pmic_power_handler);
ret = -ENODEV;
goto out_error;
}
 
status = acpi_install_address_space_handler(handle,
-   PMIC_THERMAL_OPREGION_ID,
-   intel_pmic_thermal_handler,
-   NULL, opregion);
+   PMIC_REGS_OPREGION_ID,
+   intel_pmic_regs_handler, NULL,
+   opregion);
if (ACP

Re: [PATCH v3 0/3] acpi/pmic: add opregion driver for Intel BXT WhiskeyCove PMIC

2016-06-23 Thread Bin Gao
> Well, I'm dropping the old series due to comments from Aaron on the
> second patch.
> 
> I will be waiting for an update addressing the Aaron's comments in
> [2/3] and [3/3].

Right, there was no change on [1/3].
I'll address Aaron's comments and re-send all as v4. Thanks.

-Bin


[PATCH v4 0/3] acpi/pmic: add opregion driver for Intel BXT WhiskeyCove PMIC

2016-06-23 Thread Bin Gao
This series modifies the pen function signature to take bit field
and adds a new opregion driver for Intel BXT WhiskeyCove PMIC. It
also adds support for PMIC regs operation region.

Yegnesh Iyer (1):
  acpi: pmic: Modifying the pen function signature to take bit field

Ajay Thomas (1):
  acpi: pmic: Add opregion driver for Intel BXT WhiskeyCove PMIC

Chandra Sekhar Anagani (1):
 acpi: pmic: Add support for Intel BXT PMIC regs operation region

 drivers/acpi/pmic/intel_pmic.c   | 87  +++--
 drivers/acpi/pmic/intel_pmic.h   | 11  ++--
 drivers/acpi/pmic/intel_pmic_crc.c   |  5  +++--
 drivers/acpi/Kconfig |  6  +
 drivers/acpi/Makefile|  1  +
 drivers/acpi/pmic/intel_pmic_bxtwc.c |449  +++
 6 files changed, 559 insertions(+), 10 deletions(-)
 create mode 100644 drivers/acpi/pmic/intel_pmic_bxtwc.c
--
1.9.1



[PATCH v4 1/3] acpi/pmic: modify the pen function signature to take bit field

2016-06-23 Thread Bin Gao
Issue description: On some pmics, the policy enable for thermal alerts
refers to different bit fields of the same registers, whereas on other
pmics, the policy enable refers to the same bit field on different
registers. Previous implementation did not provide the flexibility for
supporting the first approach.

Solution: Modified the policy enable function to take bit field as well.
The use of bit field is left to the pmic specific opregion driver.

Signed-off-by: Yegnesh Iyer 
Signed-off-by: Bin Gao 
---
Changes in v4: none
Changes in v3: none
Changes in v2:
 - Fixed subject line.
 drivers/acpi/pmic/intel_pmic.c | 13 +++--
 drivers/acpi/pmic/intel_pmic.h |  4 ++--
 drivers/acpi/pmic/intel_pmic_crc.c |  5 +++--
 3 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/drivers/acpi/pmic/intel_pmic.c b/drivers/acpi/pmic/intel_pmic.c
index bd772cd..410e96f 100644
--- a/drivers/acpi/pmic/intel_pmic.c
+++ b/drivers/acpi/pmic/intel_pmic.c
@@ -131,7 +131,7 @@ static int pmic_thermal_aux(struct intel_pmic_opregion 
*opregion, int reg,
 }
 
 static int pmic_thermal_pen(struct intel_pmic_opregion *opregion, int reg,
-   u32 function, u64 *value)
+   int bit, u32 function, u64 *value)
 {
struct intel_pmic_opregion_data *d = opregion->data;
struct regmap *regmap = opregion->regmap;
@@ -140,12 +140,12 @@ static int pmic_thermal_pen(struct intel_pmic_opregion 
*opregion, int reg,
return -ENXIO;
 
if (function == ACPI_READ)
-   return d->get_policy(regmap, reg, value);
+   return d->get_policy(regmap, reg, bit, value);
 
if (*value != 0 && *value != 1)
return -EINVAL;
 
-   return d->update_policy(regmap, reg, *value);
+   return d->update_policy(regmap, reg, bit, *value);
 }
 
 static bool pmic_thermal_is_temp(int address)
@@ -170,13 +170,13 @@ static acpi_status intel_pmic_thermal_handler(u32 
function,
 {
struct intel_pmic_opregion *opregion = region_context;
struct intel_pmic_opregion_data *d = opregion->data;
-   int reg, result;
+   int reg, bit, result;
 
if (bits != 32 || !value64)
return AE_BAD_PARAMETER;
 
result = pmic_get_reg_bit(address, d->thermal_table,
- d->thermal_table_count, ®, NULL);
+ d->thermal_table_count, ®, &bit);
if (result == -ENOENT)
return AE_BAD_PARAMETER;
 
@@ -187,7 +187,8 @@ static acpi_status intel_pmic_thermal_handler(u32 function,
else if (pmic_thermal_is_aux(address))
result = pmic_thermal_aux(opregion, reg, function, value64);
else if (pmic_thermal_is_pen(address))
-   result = pmic_thermal_pen(opregion, reg, function, value64);
+   result = pmic_thermal_pen(opregion, reg, bit,
+   function, value64);
else
result = -EINVAL;
 
diff --git a/drivers/acpi/pmic/intel_pmic.h b/drivers/acpi/pmic/intel_pmic.h
index d4e90af..e8bfa7b 100644
--- a/drivers/acpi/pmic/intel_pmic.h
+++ b/drivers/acpi/pmic/intel_pmic.h
@@ -12,8 +12,8 @@ struct intel_pmic_opregion_data {
int (*update_power)(struct regmap *r, int reg, int bit, bool on);
int (*get_raw_temp)(struct regmap *r, int reg);
int (*update_aux)(struct regmap *r, int reg, int raw_temp);
-   int (*get_policy)(struct regmap *r, int reg, u64 *value);
-   int (*update_policy)(struct regmap *r, int reg, int enable);
+   int (*get_policy)(struct regmap *r, int reg, int bit, u64 *value);
+   int (*update_policy)(struct regmap *r, int reg, int bit, int enable);
struct pmic_table *power_table;
int power_table_count;
struct pmic_table *thermal_table;
diff --git a/drivers/acpi/pmic/intel_pmic_crc.c 
b/drivers/acpi/pmic/intel_pmic_crc.c
index fcd1852..d7f1761 100644
--- a/drivers/acpi/pmic/intel_pmic_crc.c
+++ b/drivers/acpi/pmic/intel_pmic_crc.c
@@ -141,7 +141,8 @@ static int intel_crc_pmic_update_aux(struct regmap *regmap, 
int reg, int raw)
regmap_update_bits(regmap, reg - 1, 0x3, raw >> 8) ? -EIO : 0;
 }
 
-static int intel_crc_pmic_get_policy(struct regmap *regmap, int reg, u64 
*value)
+static int intel_crc_pmic_get_policy(struct regmap *regmap,
+   int reg, int bit, u64 *value)
 {
int pen;
 
@@ -152,7 +153,7 @@ static int intel_crc_pmic_get_policy(struct regmap *regmap, 
int reg, u64 *value)
 }
 
 static int intel_crc_pmic_update_policy(struct regmap *regmap,
-   int reg, int enable)
+   int reg, int bit, int enable)
 {
int alert0;
 
-- 
1.9.1



[PATCH v4 2/3] acpi/pmic: Add opregion driver for Intel BXT WhiskeyCove PMIC

2016-06-23 Thread Bin Gao
This patch adds operation region driver for Intel BXT WhiskeyCove
PMIC. The register mapping is done as per the BXT WC data sheet.

Signed-off-by: Ajay Thomas 
Signed-off-by: Bin Gao 
---
Changes in v4:
 - Reverted(removed) regs_read() and regs_write() methods
Changes in v3:
 - Added regs_read() and regs_write() methods
Changes in v2:
 - replaced module_init() with device_initcall()
 drivers/acpi/Kconfig |   6 +
 drivers/acpi/Makefile|   1 +
 drivers/acpi/pmic/intel_pmic_bxtwc.c | 424 +++
 3 files changed, 431 insertions(+)
 create mode 100644 drivers/acpi/pmic/intel_pmic_bxtwc.c

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index b7e2e77..47cb6f6 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -519,6 +519,12 @@ config XPOWER_PMIC_OPREGION
help
  This config adds ACPI operation region support for XPower AXP288 PMIC.
 
+config BXT_WC_PMIC_OPREGION
+   bool "ACPI operation region support for BXT WhiskeyCove PMIC"
+   depends on INTEL_SOC_PMIC
+   help
+ This config adds ACPI operation region support for BXT WhiskeyCove 
PMIC.
+
 endif
 
 endif  # ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 251ce85..5da9d4b 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -99,5 +99,6 @@ obj-$(CONFIG_ACPI_EXTLOG) += acpi_extlog.o
 obj-$(CONFIG_PMIC_OPREGION)+= pmic/intel_pmic.o
 obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o
 obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o
+obj-$(CONFIG_BXT_WC_PMIC_OPREGION) += pmic/intel_pmic_bxtwc.o
 
 video-objs += acpi_video.o video_detect.o
diff --git a/drivers/acpi/pmic/intel_pmic_bxtwc.c 
b/drivers/acpi/pmic/intel_pmic_bxtwc.c
new file mode 100644
index 000..ab2c2fd
--- /dev/null
+++ b/drivers/acpi/pmic/intel_pmic_bxtwc.c
@@ -0,0 +1,424 @@
+/*
+ * intel_pmic_bxtwc.c - Intel BXT WhiskeyCove PMIC operation region driver
+ *
+ * Copyright (C) 2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "intel_pmic.h"
+
+#define WHISKEY_COVE_ALRT_HIGH_BIT_MASK 0x0F
+#define WHISKEY_COVE_ADC_HIGH_BIT(x)   (((x & 0x0F) << 8))
+#define WHISKEY_COVE_ADC_CURSRC(x) (((x & 0xF0) >> 4))
+#define VR_MODE_DISABLED0
+#define VR_MODE_AUTOBIT(0)
+#define VR_MODE_NORMAL  BIT(1)
+#define VR_MODE_SWITCH  BIT(2)
+#define VR_MODE_ECO (BIT(0)|BIT(1))
+#define VSWITCH2_OUTPUT BIT(5)
+#define VSWITCH1_OUTPUT BIT(4)
+#define VUSBPHY_CHARGE  BIT(1)
+
+static struct pmic_table power_table[] = {
+   {
+   .address = 0x0,
+   .reg = 0x63,
+   .bit = VR_MODE_AUTO,
+   }, /* VDD1 -> VDD1CNT */
+   {
+   .address = 0x04,
+   .reg = 0x65,
+   .bit = VR_MODE_AUTO,
+   }, /* VDD2 -> VDD2CNT */
+   {
+   .address = 0x08,
+   .reg = 0x67,
+   .bit = VR_MODE_AUTO,
+   }, /* VDD3 -> VDD3CNT */
+   {
+   .address = 0x0c,
+   .reg = 0x6d,
+   .bit = VR_MODE_AUTO,
+   }, /* VLFX -> VFLEXCNT */
+   {
+   .address = 0x10,
+   .reg = 0x6f,
+   .bit = VR_MODE_NORMAL,
+   }, /* VP1A -> VPROG1ACNT */
+   {
+   .address = 0x14,
+   .reg = 0x70,
+   .bit = VR_MODE_NORMAL,
+   }, /* VP1B -> VPROG1BCNT */
+   {
+   .address = 0x18,
+   .reg = 0x71,
+   .bit = VR_MODE_NORMAL,
+   }, /* VP1C -> VPROG1CCNT */
+   {
+   .address = 0x1c,
+   .reg = 0x72,
+   .bit = VR_MODE_NORMAL,
+   }, /* VP1D -> VPROG1DCNT */
+   {
+   .address = 0x20,
+   .reg = 0x73,
+   .bit = VR_MODE_NORMAL,
+   }, /* VP2A -> VPROG2ACNT */
+   {
+   .address = 0x24,
+   .reg = 0x74,
+   .bit = VR_MODE_NORMAL,
+   }, /* VP2B -> VPROG2BCNT */
+   {
+   .address = 0x28,
+   .reg = 0x75,
+   .bit = VR_MODE_NORMAL,
+   }, /* VP2C -> VPROG2CCNT */
+   {
+   .address = 0x2c,
+   .reg = 0x76,
+   .bit = VR_MODE_NORMAL,
+   }, /* VP3A -> VPROG3ACNT */
+   {
+   .addres

[PATCH v4 3/3] acpi/pmic: Add support for PMIC regs operation region

2016-06-23 Thread Bin Gao
Broxton platform firmware has defined new customized operation regions
called regs for PMIC chip - regs op region is used to handle the
PMIC gpio mainly intended for the TYPE-C VBUS and Orientation.

The intel_gpio_ctx  structure is created for the purpose of handling
the PMIC gpio register read and write.

Signed-off-by: Felipe Balbi 
Signed-off-by: Chandra Sekhar Anagani 
Signed-off-by: Bin Gao 
---
Changes in v4:
 - various fixes to address Aaron's comments.
Changes in v3: none
Changes in v2: none
 drivers/acpi/pmic/intel_pmic.c | 74 --
 drivers/acpi/pmic/intel_pmic.h |  5 +++
 2 files changed, 76 insertions(+), 3 deletions(-)

diff --git a/drivers/acpi/pmic/intel_pmic.c b/drivers/acpi/pmic/intel_pmic.c
index 410e96f..e11d1e0 100644
--- a/drivers/acpi/pmic/intel_pmic.c
+++ b/drivers/acpi/pmic/intel_pmic.c
@@ -21,12 +21,14 @@
 
 #define PMIC_POWER_OPREGION_ID 0x8d
 #define PMIC_THERMAL_OPREGION_ID   0x8c
+#define PMIC_REGS_OPREGION_ID  0x8f
 
 struct intel_pmic_opregion {
struct mutex lock;
struct acpi_lpat_conversion_table *lpat_table;
struct regmap *regmap;
struct intel_pmic_opregion_data *data;
+   struct pmic_gpio_ctxctx;
 };
 
 static int pmic_get_reg_bit(int address, struct pmic_table *table,
@@ -204,6 +206,56 @@ static acpi_status intel_pmic_thermal_handler(u32 function,
return AE_OK;
 }
 
+static acpi_status intel_pmic_gpio_handler(u32 function,
+   acpi_physical_address address, u32 bits, u64 *value64,
+   void *handler_context, void *region_context)
+{
+   struct intel_pmic_opregion *opregion = region_context;
+   int result;
+
+   switch (address) {
+   case 0:
+   return AE_OK;
+   case 1:
+   opregion->ctx.address |= (*value64 & 0xff) << 8;
+   return AE_OK;
+   case 2:
+   opregion->ctx.address |= *value64 & 0xff;
+   return AE_OK;
+   case 3:
+   opregion->ctx.value = *value64 & 0xff;
+   return AE_OK;
+   case 4:
+   if (*value64) {
+   result = regmap_write(opregion->regmap,
+opregion->ctx.address,
+   opregion->ctx.value);
+   } else {
+   result = regmap_read(opregion->regmap,
+   opregion->ctx.address,
+   &opregion->ctx.value);
+   if (result == 0)
+   *value64 = opregion->ctx.value;
+   }
+   memset(&opregion->ctx, 0x00, sizeof(opregion->ctx));
+   break;
+   default:
+   pr_err("%s(): Inavlid address %llu, please check the BIOS\n",
+__func__, address);
+   return AE_ERROR;
+   }
+
+   if (result < 0) {
+   if (result == -EINVAL)
+   return AE_BAD_PARAMETER;
+   else
+   return AE_ERROR;
+   }
+
+   return AE_OK;
+}
+
+
 int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
struct regmap *regmap,
struct intel_pmic_opregion_data *d)
@@ -240,15 +292,31 @@ int intel_pmic_install_opregion_handler(struct device 
*dev, acpi_handle handle,
intel_pmic_thermal_handler,
NULL, opregion);
if (ACPI_FAILURE(status)) {
-   acpi_remove_address_space_handler(handle, 
PMIC_POWER_OPREGION_ID,
- intel_pmic_power_handler);
ret = -ENODEV;
-   goto out_error;
+   goto remove_pmic_power_handler;
+   }
+
+   status = acpi_install_address_space_handler(handle,
+   PMIC_REGS_OPREGION_ID,
+   intel_pmic_gpio_handler,
+   NULL, opregion);
+   if (ACPI_FAILURE(status)) {
+   ret = -ENODEV;
+   goto remove_pmic_thermal_handler;
}
 
opregion->data = d;
return 0;
 
+remove_pmic_thermal_handler:
+   acpi_remove_address_space_handler(handle,
+   PMIC_POWER_OPREGION_ID,
+   intel_pmic_thermal_handler);
+remove_pmic_power_handler:
+   acpi_remove_address_space_handler(handle,
+   PMIC_POWER_OPREGION_ID,
+   intel_pmic_power_handler);
+
 out_e

Re: [PATCH v4] gpio: add Intel WhiskeyCove GPIO driver

2016-07-06 Thread Bin Gao
On Wed, Jul 06, 2016 at 10:57:19AM +0200, Linus Walleij wrote:
> > +static irqreturn_t wcove_gpio_irq_handler(int irq, void *data)
> > +{
> > +   int pending;
> > +   unsigned int p0, p1, virq, gpio;
> > +   struct wcove_gpio *wg = data;
> > +
> > +   if (regmap_read(wg->regmap, IRQ_STATUS_OFFSET + 0, &p0) ||
> > +   regmap_read(wg->regmap, IRQ_STATUS_OFFSET + 1, &p1)) {
> 
> Why can't you use regmap_bulk_read() here?

Will fix this in v5.

> 
> > +   dev_err(wg->chip.parent, "%s(): regmap_read() failed.\n",
> > +   __func__);
> > +   return IRQ_NONE;
> > +   }
> > +
> > +   pending = p0 | (p1 << 8);
> > +
> > +   for (gpio = 0; gpio < WCOVE_GPIO_NUM; gpio++) {
> > +   if (pending & BIT(gpio)) {
> > +   virq = irq_find_mapping(wg->chip.irqdomain, gpio);
> > +   handle_nested_irq(virq);
> > +   }
> > +   }
> > +
> > +   regmap_write(wg->regmap, IRQ_STATUS_OFFSET + 0, p0);
> > +   regmap_write(wg->regmap, IRQ_STATUS_OFFSET + 1, p1);
> 
> Use regmap_bulk_write()?

Will fix this in v5.

> 
> Also you're ignoring the return error code. Check it and dev_err() if
> it fails.

Yes, will fix.

> 
> This loop seems like it could miss interrupts happening while
> processing. Especially edge interrupts, and thatr will lead to serious
> bugs later.
> 
> Please consider the following construction:
> 
> 1. read status register
> 2. Any IRQs active?
>   2.1 No IRQs active: if this is the FIRST iteration, exit with IRQ_NONE
>   2.2 No IRQs active If this the second iteration or later, exit with
> IRQ_HANDLED
>   2.3 IRQs active, continue
> 2. Find first active IRQ
> 3. Handle first active IRQ
> 4. ACK the first active IRQ by writing the status register
> 5. Reiterate from 1
> 
> This way, if two IRQs happen at the same time, or if a new IRQ appears
> while you're inside the interrupt handler, it gets served.

I agree. Writing to status register should be done bit by bit, instead of
one write for all bits. Will fix this in v5.

> 
> > +static void wcove_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
> > +{
> > +   struct wcove_gpio *wg = gpiochip_get_data(chip);
> > +   int gpio, offset, group;
> > +   unsigned int ctlo, ctli, irq_mask, irq_status;
> > +
> > +   for (gpio = 0; gpio < WCOVE_GPIO_NUM; gpio++) {
> > +   group = gpio < GROUP0_NR_IRQS ? 0 : 1;
> > +   regmap_read(wg->regmap, to_reg(gpio, CTRL_OUT), &ctlo);
> > +   regmap_read(wg->regmap, to_reg(gpio, CTRL_IN), &ctli);
> > +   regmap_read(wg->regmap, IRQ_MASK_OFFSET + group, &irq_mask);
> > +   regmap_read(wg->regmap, IRQ_STATUS_OFFSET + group, 
> > &irq_status);
> 
> Ignoring error codes. Fix this.

Will Fix in v5.

> 
> > +   gpiochip_irqchip_add(&wg->chip, &wcove_irqchip, 0,
> > +handle_simple_irq, IRQ_TYPE_NONE);
> 
> Reexamine the use of handle_simple_irq() here. We have two kinds of
> irq hardware: those with one register for ACKing and reading the status
> of an IRQ, and those with two registers for it: one where you ACK the
> IRQ (so it can immediately re-trigger) and one to read the status of
> whether it happened. Sometimes different handling is needed for
> levek and edge IRQs even (c.f. gpio-pl061.c).
> 
> Only the hardware with just one register for both things should use
> handle_simple_irq(). This seems to be the case here but I want you
> to verify.

I will check and fix if it's needed.

> 
> Yours,
> Linus Walleij

Thanks for your review.


Re: [PATCH v4] gpio: add Intel WhiskeyCove GPIO driver

2016-07-06 Thread Bin Gao
On Wed, Jul 06, 2016 at 01:07:15PM +0300, Mika Westerberg wrote:
> On Wed, Jul 06, 2016 at 10:57:19AM +0200, Linus Walleij wrote:
> > On Tue, Jun 28, 2016 at 1:56 AM, Bin Gao  wrote:
> > 
> > > This patch introduces a separate GPIO driver for Intel WhiskeyCove PMIC.
> > > This driver is based on gpio-crystalcove.c.
> > >
> > > Signed-off-by: Ajay Thomas 
> > > Signed-off-by: Bin Gao 
> > > ---
> > > Changes in v4:
> > >  - Converted CTLI_INTCNT_XX macros to less verbose ones INT_DETECT_XX.
> > >  - Add comments about why there is no .pm for the driver.
> > >  - Header files re-ordered.
> > >  - Various coding style change to address Andy's comments.
> > 
> > Mika can I have your ACK/review tag on this driver so I can merge it?
> > I prefer to have all Intel stuff bearing your seal of approval.
> 
> Thanks for your trust :)
> 
> I don't have much comments in addition to what you already pointed out.
> I'll just wait for the next revision and give my ack then.
> 
> > > +static irqreturn_t wcove_gpio_irq_handler(int irq, void *data)
> > > +{
> > > +   int pending;
> > > +   unsigned int p0, p1, virq, gpio;
> > > +   struct wcove_gpio *wg = data;
> 
> Bin,
> 
> Since you are going to make another iteration, please arrange the
> declarations like:
> 
>   unsigned int p0, p1, virq, gpio;
>   struct wcove_gpio *wg = data;
>   int pending;

Yes, will do. Thanks.

-Bin


Re: [PATCH] gpio: add Intel WhiskeyCove GPIO driver

2016-06-14 Thread Bin Gao
On Tue, Jun 14, 2016 at 01:09:31PM +0300, Mika Westerberg wrote:
> On Fri, Jun 10, 2016 at 11:01:51PM -0700, Bin Gao wrote:
> > +static const struct platform_device_id pmic_gpio_id_table[] = {
> > +   { "bxt_wcove_gpio", },
> > +};
> 
> Do you really need this?
> 
> > +
> > +static struct platform_driver wcove_gpio_driver = {
> > +   .probe = wcove_gpio_probe,
> > +   .remove = wcove_gpio_remove,
> > +   .driver = {
> > +   .name = "wcove_gpio",
> > +   },
> > +   .id_table = pmic_gpio_id_table,
> 
> and this?
> 
> > +};
> > +
> > +module_platform_driver(wcove_gpio_driver);
> > +
> > +MODULE_AUTHOR("Ajay Thomas ");
> > +MODULE_DESCRIPTION("Intel Whiskey Cove GPIO Driver");
> > +MODULE_LICENSE("GPL v2");
> 
> You can add
> 
> MODULE_ALIAS("platform:wcove_gpio");
> 
> to get the module loaded automatically.

Mika,
Thanks for your review. I'll address these in patch v2.

-Bin


[PATCH 0/2] usb: typec: Introduce USB PD sink state machine driver and add PD sink support for Intel BXT PMIC Type-C phy

2016-07-14 Thread Bin Gao
This series introduce a USB PD(Power Delivery) sink port simple state
machine driver and adds USB PD sink port support for Intel BXT Whiskey
Cove PMIC Type-C phy driver.

This series depends on these two patches:
https://lkml.org/lkml/2016/6/29/349
https://lkml.org/lkml/2016/6/29/350

Bin Gao (1):
  usb: typec: Add USB Power Delivery sink port support

Chandra Sekhar Anagani (1):
  usb: typec: add PD sink port support for Intel Whiskey Cove PMIC USB
  Type-C PHY driver

 drivers/usb/typec/Kconfig   |  13 +
 drivers/usb/typec/Makefile  |   1 +
 drivers/usb/typec/pd_sink.c | 967 +
 include/linux/usb/pd_message.h  | 371 
 include/linux/usb/pd_sink.h | 286 
 drivers/usb/typec/typec_wcove.c | 289 
 6 files changed, 1901 insertions(+), 26 deletions(-)
 create mode 100644 drivers/usb/typec/pd_sink.c
 create mode 100644 include/linux/usb/pd_message.h
 create mode 100644 include/linux/usb/pd_sink.h
--
1.9.1


[PATCH 1/2] usb: typec: Add USB Power Delivery sink port support

2016-07-14 Thread Bin Gao
This patch implements a simple USB Power Delivery sink port state machine.
It assumes the hardware only handles PD packet transmitting and receiving
over the CC line of the USB Type-C connector. The state transition is
completely controlled by software. This patch only implement the sink port
function and it doesn't support source port and port swap yet.

This patch depends on these two patches:
https://lkml.org/lkml/2016/6/29/349
https://lkml.org/lkml/2016/6/29/350

Signed-off-by: Bin Gao 
---
 drivers/usb/typec/Kconfig  |  13 +
 drivers/usb/typec/Makefile |   1 +
 drivers/usb/typec/pd_sink.c| 967 +
 include/linux/usb/pd_message.h | 371 
 include/linux/usb/pd_sink.h| 286 
 5 files changed, 1638 insertions(+)
 create mode 100644 drivers/usb/typec/pd_sink.c
 create mode 100644 include/linux/usb/pd_message.h
 create mode 100644 include/linux/usb/pd_sink.h

diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig
index 7a345a4..a04a900 100644
--- a/drivers/usb/typec/Kconfig
+++ b/drivers/usb/typec/Kconfig
@@ -4,12 +4,25 @@ menu "USB PD and Type-C drivers"
 config TYPEC
tristate
 
+config USB_PD_SINK
+   bool "USB Power Delivery Sink Port State Machine Driver"
+   select TYPEC
+   help
+ Enable this to support USB PD(Power Delivery) Sink port.
+ This driver implements a simple USB PD sink state machine.
+ The underlying TypeC phy driver is responsible for cable
+ plug/unplug event, port orientation detection, transmitting
+ and receiving PD messages. This driver only process messages
+ received by the TypeC phy driver and maintain the sink port's
+ state machine.
+
 config TYPEC_WCOVE
tristate "Intel WhiskeyCove PMIC USB Type-C PHY driver"
depends on ACPI
depends on INTEL_SOC_PMIC
depends on INTEL_PMC_IPC
select TYPEC
+   select USB_PD_SINK
help
  This driver adds support for USB Type-C detection on Intel Broxton
  platforms that have Intel Whiskey Cove PMIC. The driver can detect the
diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
index b9cb862..a62eb57 100644
--- a/drivers/usb/typec/Makefile
+++ b/drivers/usb/typec/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_TYPEC)+= typec.o
 obj-$(CONFIG_TYPEC_WCOVE)  += typec_wcove.o
+obj-$(CONFIG_USB_PD_SINK)  += pd_sink.o
diff --git a/drivers/usb/typec/pd_sink.c b/drivers/usb/typec/pd_sink.c
new file mode 100644
index 000..374bdef
--- /dev/null
+++ b/drivers/usb/typec/pd_sink.c
@@ -0,0 +1,967 @@
+/*
+ * pd_sink.c - USB PD (Power Delivery) sink port state machine driver
+ *
+ * This driver implements a simple USB PD sink port state machine.
+ * It assumes the upper layer, i.e. the user of this driver, handles
+ * the PD message receiving and transmitting. The upper layer receives
+ * PD messages from the Source, queues them to us, and when processing
+ * the received message we'll call upper layer's transmitting function
+ * to send PD messages to the source.
+ * The sink port state machine is maintained in this driver but we also
+ * broadcast some important PD messages to upper layer as events.
+ *
+ * Copyright (C) 2016 Intel Corporation
+ *
+ * Author: Bin Gao 
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+#include 
+#include 
+
+#define MAKE_HEADER(port, header, msg, objs) \
+do { \
+   header->type = msg; \
+   header->data_role = PD_DATA_ROLE_UFP; \
+   header->revision = port->pd_rev; \
+   header->power_role = PD_POWER_ROLE_SINK; \
+   header->id = roll_msg_id(port); \
+   header->nr_objs = objs; \
+   header->extended = PD_MSG_NOT_EXTENDED; \
+} while (0)
+
+static struct pd_sink_port *sink_ports[MAX_NR_SINK_PORTS];
+static int nr_ports;
+
+BLOCKING_NOTIFIER_HEAD(pd_sink_notifier_list);
+
+static char *state_strings[] = {
+   "WAIT_FOR_SOURCE_CAPABILITY",
+   "REQUEST_SENT",
+   "ACCEPT_RECEIVED",
+   "POWER_SUPPLY_READY",
+};
+
+/* Control messages */
+static char *cmsg_strings[] = {
+   "GOODCRC",  /* 1 */
+   "GOTOMIN",  /* 2 */
+   "ACCEPT",   /* 3 */
+   "REJECT",   /* 4 */
+   "PING", /* 5 */
+   "PS_RDY",   /* 6 */
+   "GET_SRC_CAP",  /* 7 */
+   "GET_SINK_CAP", /* 8 */
+   "DR_SWAP",  

[PATCH 2/2] usb: typec: add PD sink port support for Intel Whiskey Cove PMIC Typc-C PHY driver

2016-07-14 Thread Bin Gao
From: Chandra Sekhar Anagani 

This adds PD sink port support for the USB Type-C PHY on Intel WhiskeyCove
PMIC which is available on some of the Intel Broxton SoC based platforms.

This patch depends on these two patches:
https://lkml.org/lkml/2016/6/29/349
https://lkml.org/lkml/2016/6/29/350

Signed-off-by: Chandra Sekhar Anagani 
---
 drivers/usb/typec/typec_wcove.c | 289 
 1 file changed, 263 insertions(+), 26 deletions(-)

diff --git a/drivers/usb/typec/typec_wcove.c b/drivers/usb/typec/typec_wcove.c
index c7c2d28..a4250ba 100644
--- a/drivers/usb/typec/typec_wcove.c
+++ b/drivers/usb/typec/typec_wcove.c
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2016 Intel Corporation
  * Author: Heikki Krogerus 
+ * Author: Chandra Sekhar Anagani 
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -10,9 +11,11 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -25,6 +28,7 @@
 #define USBC_CONTROL3  0x7003
 #define USBC_CC1_CTRL  0x7004
 #define USBC_CC2_CTRL  0x7005
+#define USBC_CC_SEL0x7006
 #define USBC_STATUS1   0x7007
 #define USBC_STATUS2   0x7008
 #define USBC_STATUS3   0x7009
@@ -32,7 +36,16 @@
 #define USBC_IRQ2  0x7016
 #define USBC_IRQMASK1  0x7017
 #define USBC_IRQMASK2  0x7018
-
+#define USBC_PD_CFG1   0x7019
+#define USBC_PD_CFG2   0x701a
+#define USBC_PD_CFG3   0x701b
+#define USBC_PD_STATUS 0x701c
+#define USBC_RX_STATUS 0x701d
+#define USBC_RX_INFO   0x701e
+#define USBC_TX_CMD0x701f
+#define USBC_TX_INFO   0x7020
+#define USBC_RX_DATA_START 0x7028
+#define USBC_TX_DATA_START 0x7047
 /* Register bits */
 
 #define USBC_CONTROL1_MODE_DRP(r)  ((r & ~0x7) | 4)
@@ -44,7 +57,9 @@
 #define USBC_CONTROL3_PD_DIS   BIT(1)
 
 #define USBC_CC_CTRL_VCONN_EN  BIT(1)
+#define USBC_CC_CTRL_TX_EN BIT(2)
 
+#define USBC_CC_SEL_CCSEL  (BIT(0) | BIT(1))
 #define USBC_STATUS1_DET_ONGOING   BIT(6)
 #define USBC_STATUS1_RSLT(r)   (r & 0xf)
 #define USBC_RSLT_NOTHING  0
@@ -79,11 +94,44 @@
 USBC_IRQ2_RX_HR | USBC_IRQ2_RX_CR | \
 USBC_IRQ2_TX_SUCCESS | USBC_IRQ2_TX_FAIL)
 
+#define USBC_PD_CFG1_ID_FILL   BIT(7)
+
+#define USBC_PD_CFG2_SOP_RXBIT(0)
+
+#define USBC_PD_CFG3_SR_SOP2   (BIT(7) | BIT(6))
+#define USBC_PD_CFG3_SR_SOP1   (BIT(5) | BIT(4))
+#define USBC_PD_CFG3_SR_SOP0   (BIT(3) | BIT(2))
+#define USBC_PD_CFG3_DATAROLE  BIT(1)
+#define USBC_PD_CFG3_PWRROLE   BIT(0)
+
+#define USBC_TX_CMD_TXBUF_RDY  BIT(0)
+#define USBC_TX_CMD_TX_START   BIT(1)
+#define USBC_TX_CMD_TXBUF_CMD(r)   ((r >> 5) & 0x7)
+
+#define USBC_TX_INFO_TX_SOP(BIT(0) | BIT(1) | BIT(2))
+#define USBC_TX_INFO_TX_RETRIES(BIT(3) | BIT(4) | BIT(5))
+
+#define USBC_RX_STATUS_RX_DATA BIT(7)
+#define USBC_RX_STATUS_RX_OVERRUN  BIT(6)
+#define USBC_RX_STATUS_RX_CLEARBIT(0)
+
+#define USBC_PD_STATUS_RX_RSLT(r)  ((r >> 3) & 0x7)
+#define USBC_PD_STATUS_TX_RSLT(r)  (r & 0x7)
+
+#define USBC_RX_INFO_RXBYTES(r)((r >> 3) & 0x1f)
+#define USBC_RX_INFO_RX_SOP(r) (r & 0x7)
+
+#define USBC_PD_RX_BUF_LEN 30
+#define USBC_PD_TX_BUF_LEN 30
+
 struct wcove_typec {
+   int pd_port_num;
struct mutex lock; /* device lock */
struct device *dev;
struct regmap *regmap;
struct typec_port *port;
+   struct pd_sink_port pd_port;
+   struct completion complete;
struct typec_capability cap;
struct typec_connection con;
struct typec_partner partner;
@@ -106,6 +154,50 @@ enum wcove_typec_role {
WCOVE_ROLE_DEVICE,
 };
 
+static struct sink_ps profiles[] = {
+
+   {
+   .ps_type = PS_TYPE_FIXED,
+   .ps_fixed = {
+   .voltage_fixed  = 100,  /* 5V/50mV = 100 */
+   .current_default = 90,  /* 900mA/10mA = 90 */
+   .current_max= 90,   /* 900mA/10mA = 90 */
+   },
+
+   },
+
+   {
+   .ps_type = PS_TYPE_FIXED,
+   .ps_fixed = {
+   .voltage_fixed  = 100,
+   .current_default = 300,
+   .current_max= 300,
+   },
+   },
+
+   {
+   .ps_type = PS_TYPE_FIXED,
+   .ps_fixed = {
+   .voltage_fixed  = 240,
+   .current_default = 300,
+   .current_max= 300,
+   },
+   },
+
+};
+
+static struct pd_sink_profile profile = {
+   .hw_goodcrc_tx =

[PATCH v7] gpio: add Intel WhiskeyCove PMIC GPIO driver

2016-07-25 Thread Bin Gao
This patch introduces a separate GPIO driver for Intel WhiskeyCove PMIC.
This driver is based on gpio-crystalcove.c.

Signed-off-by: Ajay Thomas 
Signed-off-by: Bin Gao 
Reviewed-by: Andy Shevchenko 
Reviewed-by: Mika Westerberg 
---
Changes in v7:
 - Fixed various coding style comments from Andy Shevchenko
Changes in v6:
 - Removed unnecessary wcove_gpio_remove()
 - Used devm_gpiochip_remove() instead of gpiochip_remove()
 - Various coding style changes per Mika's comment
Changes in v5:
 - Revisited the interrupt handler code to iterate until all pending
   interrupts are handled. This change is to avoid missing interrupt
   when we're inside the interrupt handler.
 - Used regmap_bulk_read() to read address adjacent registers.
Changes in v4:
 - Converted CTLI_INTCNT_XX macros to less verbose ones INT_DETECT_XX.
 - Add comments about why there is no .pm for the driver.
 - Header files re-ordered.
 - Various coding style change to address Andy's comments.
Changes in v3:
 - Fixed the year in copyright line(2015-->2016).
 - Removed DRV_NAME macro.
 - Added kernel-doc for regmap_irq_chip of the wcove_gpio structure.
 - Line length fix.
Changes in v2:
 - Typo fix (Whsikey --> Whiskey).
 - Included linux/gpio/driver.h instead of linux/gpio.h
 - Implemented .set_single_ended().
 - Added GPIO register description.
 - Replaced container_of() with gpiochip_get_data().
 - Removed unnecessary "if (gpio > WCOVE_VGPIO_NUM" check.
 - Removed the device id table and added MODULE_ALIAS().
 drivers/gpio/Kconfig  |  13 ++
 drivers/gpio/Makefile |   1 +
 drivers/gpio/gpio-wcove.c | 455 ++
 3 files changed, 469 insertions(+)
 create mode 100644 drivers/gpio/gpio-wcove.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 536112f..240ae7c 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -972,6 +972,19 @@ config GPIO_UCB1400
  This enables support for the Philips UCB1400 GPIO pins.
  The UCB1400 is an AC97 audio codec.
 
+config GPIO_WHISKEY_COVE
+   tristate "GPIO support for Whiskey Cove PMIC"
+   depends on INTEL_SOC_PMIC
+   select GPIOLIB_IRQCHIP
+   help
+ Support for GPIO pins on Whiskey Cove PMIC.
+
+ Say Yes if you have a Intel SoC based tablet with Whiskey Cove PMIC
+ inside.
+
+ This driver can also be built as a module. If so, the module will be
+ called gpio-wcove.
+
 config GPIO_WM831X
tristate "WM831x GPIOs"
depends on MFD_WM831X
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 991598e..fff27b0 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -118,6 +118,7 @@ obj-$(CONFIG_GPIO_VF610)+= gpio-vf610.o
 obj-$(CONFIG_GPIO_VIPERBOARD)  += gpio-viperboard.o
 obj-$(CONFIG_GPIO_VR41XX)  += gpio-vr41xx.o
 obj-$(CONFIG_GPIO_VX855)   += gpio-vx855.o
+obj-$(CONFIG_GPIO_WHISKEY_COVE)+= gpio-wcove.o
 obj-$(CONFIG_GPIO_WM831X)  += gpio-wm831x.o
 obj-$(CONFIG_GPIO_WM8350)  += gpio-wm8350.o
 obj-$(CONFIG_GPIO_WM8994)  += gpio-wm8994.o
diff --git a/drivers/gpio/gpio-wcove.c b/drivers/gpio/gpio-wcove.c
new file mode 100644
index 000..f5c88df
--- /dev/null
+++ b/drivers/gpio/gpio-wcove.c
@@ -0,0 +1,455 @@
+/*
+ * Intel Whiskey Cove PMIC GPIO Driver
+ *
+ * This driver is written based on gpio-crystalcove.c
+ *
+ * Copyright (C) 2016 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * Whiskey Cove PMIC has 13 physical GPIO pins divided into 3 banks:
+ * Bank 0: Pin 0 - 6
+ * Bank 1: Pin 7 - 10
+ * Bank 2: Pin 11 -12
+ * Each pin has one output control register and one input control register.
+ */
+#define BANK0_NR_PINS  7
+#define BANK1_NR_PINS  4
+#define BANK2_NR_PINS  2
+#define WCOVE_GPIO_NUM (BANK0_NR_PINS + BANK1_NR_PINS + BANK2_NR_PINS)
+#define WCOVE_VGPIO_NUM94
+/* GPIO output control registers (one per pin): 0x4e44 - 0x4e50 */
+#define GPIO_OUT_CTRL_BASE 0x4e44
+/* GPIO input control registers (one per pin): 0x4e51 - 0x4e5d */
+#define GPIO_IN_CTRL_BASE  0x4e51
+
+/*
+ * GPIO interrupts are organized in two groups:
+ * Group 0: Bank 0 pins (Pin 0 - 6)
+ * Group 1: Bank 1 and Bank 2 pins (Pin 7 - 12)
+ * Each group has two registers (one bit per pin): status and mask.
+ */
+#define GROUP0_NR_IRQS 7
+#define GROUP1_NR_IRQS 6
+#define 

[PATCH v2 0/2] usb: typec: Introduce USB PD sink state machine driver and add PD sink support for Intel BXT PMIC Type-C phy

2016-07-26 Thread Bin Gao
This series introduce a USB PD(Power Delivery) sink port simple state
machine driver and adds USB PD sink port support for Intel BXT Whiskey
Cove PMIC Type-C phy driver.

This series depends on these two patches:
https://lkml.org/lkml/2016/6/29/349
https://lkml.org/lkml/2016/6/29/350

Bin Gao (1):
  usb: typec: Add USB Power Delivery sink port support

Chandra Sekhar Anagani (1):
  usb: typec: add PD sink port support for Intel Whiskey Cove PMIC USB
  Type-C PHY driver

 drivers/usb/typec/Kconfig   |  11 +
 drivers/usb/typec/Makefile  |   1 +
 drivers/usb/typec/pd_sink.c | 908 +
 include/linux/usb/pd_message.h  | 369 +
 include/linux/usb/pd_sink.h | 299 ++
 drivers/usb/typec/typec_wcove.c | 309 
 6 files changed, 1873 insertions(+), 24 deletions(-)
 create mode 100644 drivers/usb/typec/pd_sink.c
 create mode 100644 include/linux/usb/pd_message.h
 create mode 100644 include/linux/usb/pd_sink.h
--
1.9.1


[PATCH v2 1/2] usb: typec: Add USB Power Delivery sink port support

2016-07-26 Thread Bin Gao
This patch implements a simple USB Power Delivery sink port state machine.
It assumes the hardware only handles PD packet transmitting and receiving
over the CC line of the USB Type-C connector. The state transition is
completely controlled by software. This patch only implement the sink port
function and it doesn't support source port and port swap yet.

This patch depends on these two patches:
https://lkml.org/lkml/2016/6/29/349
https://lkml.org/lkml/2016/6/29/350

Signed-off-by: Bin Gao 
Changes in v2:
 - Removed work queue so messages are directly handled in phy driver's 
interrupt context
 - used pr_debug instead of pr_info for message dump
 - Converted PD driver to tristate and typec driver is independent of it
---
 drivers/usb/typec/Kconfig  |  11 +
 drivers/usb/typec/Makefile |   1 +
 drivers/usb/typec/pd_sink.c| 908 +
 include/linux/usb/pd_message.h | 369 +
 include/linux/usb/pd_sink.h| 299 ++
 5 files changed, 1588 insertions(+)
 create mode 100644 drivers/usb/typec/pd_sink.c
 create mode 100644 include/linux/usb/pd_message.h
 create mode 100644 include/linux/usb/pd_sink.h

diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig
index 7a345a4..662aa54 100644
--- a/drivers/usb/typec/Kconfig
+++ b/drivers/usb/typec/Kconfig
@@ -4,6 +4,17 @@ menu "USB PD and Type-C drivers"
 config TYPEC
tristate
 
+config USB_PD_SINK
+   tristate "USB Power Delivery Sink Port State Machine Driver"
+   help
+ Enable this to support USB PD(Power Delivery) Sink port.
+ This driver implements a simple USB PD sink state machine.
+ The underlying TypeC phy driver is responsible for cable
+ plug/unplug event, port orientation detection, transmitting
+ and receiving PD messages. This driver only process messages
+ received by the TypeC phy driver and maintain the sink port's
+ state machine.
+
 config TYPEC_WCOVE
tristate "Intel WhiskeyCove PMIC USB Type-C PHY driver"
depends on ACPI
diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
index b9cb862..74aad6c 100644
--- a/drivers/usb/typec/Makefile
+++ b/drivers/usb/typec/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_TYPEC)+= typec.o
+obj-$(CONFIG_USB_PD_SINK)  += pd_sink.o
 obj-$(CONFIG_TYPEC_WCOVE)  += typec_wcove.o
diff --git a/drivers/usb/typec/pd_sink.c b/drivers/usb/typec/pd_sink.c
new file mode 100644
index 000..1e46d3c
--- /dev/null
+++ b/drivers/usb/typec/pd_sink.c
@@ -0,0 +1,908 @@
+/*
+ * pd_sink.c - USB PD (Power Delivery) sink port state machine driver
+ *
+ * This driver implements a simple USB PD sink port state machine.
+ * It assumes the upper layer, i.e. the user of this driver, handles
+ * the PD message receiving and transmitting. The upper layer receives
+ * PD messages from the Source, queues them to us, and when processing
+ * the received message we'll call upper layer's transmitting function
+ * to send PD messages to the source.
+ * The sink port state machine is maintained in this driver but we also
+ * broadcast some important PD messages to upper layer as events.
+ *
+ * Copyright (C) 2016 Intel Corporation
+ *
+ * Author: Bin Gao 
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+#include 
+#include 
+
+#define MAKE_HEADER(port, header, msg, objs) \
+do { \
+   header->type = msg; \
+   header->data_role = PD_DATA_ROLE_UFP; \
+   header->revision = port->pd_rev; \
+   header->power_role = PD_POWER_ROLE_SINK; \
+   header->id = roll_msg_id(port); \
+   header->nr_objs = objs; \
+   header->extended = PD_MSG_NOT_EXTENDED; \
+} while (0)
+
+static struct pd_sink_port *sink_ports[MAX_NR_SINK_PORTS];
+static int nr_ports;
+
+BLOCKING_NOTIFIER_HEAD(pd_sink_notifier_list);
+
+static char *state_strings[] = {
+   "WAIT_FOR_SOURCE_CAPABILITY",
+   "REQUEST_SENT",
+   "ACCEPT_RECEIVED",
+   "POWER_SUPPLY_READY",
+};
+
+/* Control messages */
+static char *cmsg_strings[] = {
+   "GOODCRC",  /* 1 */
+   "GOTOMIN",  /* 2 */
+   "ACCEPT",   /* 3 */
+   "REJECT",   /* 4 */
+   "PING", /* 5 */
+   "PS_RDY",   /* 6 */
+   "GET_SRC_CAP",  /* 7 */
+   "GET_SINK_CAP", /* 8 */
+   "DR_SWAP",  /* 9 */
+   "PR_SWAP",  /* 

[PATCH v2 2/2] usb: typec: add PD sink port support for Intel Whiskey Cove PMIC Typc-C PHY driver

2016-07-26 Thread Bin Gao
From: Chandra Sekhar Anagani 

This adds PD sink port support for the USB Type-C PHY on Intel WhiskeyCove
PMIC which is available on some of the Intel Broxton SoC based platforms.

This patch depends on these two patches:
https://lkml.org/lkml/2016/6/29/349
https://lkml.org/lkml/2016/6/29/350

Signed-off-by: Chandra Sekhar Anagani 
Signed-off-by: Pranav Tipnis 
Signed-off-by: Bin Gao 
Changes in v2:
 - Added PD support for cold boot case
---
 drivers/usb/typec/typec_wcove.c | 309 
 1 file changed, 285 insertions(+), 24 deletions(-)

diff --git a/drivers/usb/typec/typec_wcove.c b/drivers/usb/typec/typec_wcove.c
index c7c2d28..000d6ae 100644
--- a/drivers/usb/typec/typec_wcove.c
+++ b/drivers/usb/typec/typec_wcove.c
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2016 Intel Corporation
  * Author: Heikki Krogerus 
+ * Author: Chandra Sekhar Anagani 
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -10,9 +11,11 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -25,6 +28,7 @@
 #define USBC_CONTROL3  0x7003
 #define USBC_CC1_CTRL  0x7004
 #define USBC_CC2_CTRL  0x7005
+#define USBC_CC_SEL0x7006
 #define USBC_STATUS1   0x7007
 #define USBC_STATUS2   0x7008
 #define USBC_STATUS3   0x7009
@@ -32,7 +36,16 @@
 #define USBC_IRQ2  0x7016
 #define USBC_IRQMASK1  0x7017
 #define USBC_IRQMASK2  0x7018
-
+#define USBC_PD_CFG1   0x7019
+#define USBC_PD_CFG2   0x701a
+#define USBC_PD_CFG3   0x701b
+#define USBC_PD_STATUS 0x701c
+#define USBC_RX_STATUS 0x701d
+#define USBC_RX_INFO   0x701e
+#define USBC_TX_CMD0x701f
+#define USBC_TX_INFO   0x7020
+#define USBC_RX_DATA_START 0x7028
+#define USBC_TX_DATA_START 0x7047
 /* Register bits */
 
 #define USBC_CONTROL1_MODE_DRP(r)  ((r & ~0x7) | 4)
@@ -44,7 +57,9 @@
 #define USBC_CONTROL3_PD_DIS   BIT(1)
 
 #define USBC_CC_CTRL_VCONN_EN  BIT(1)
+#define USBC_CC_CTRL_TX_EN BIT(2)
 
+#define USBC_CC_SEL_CCSEL  (BIT(0) | BIT(1))
 #define USBC_STATUS1_DET_ONGOING   BIT(6)
 #define USBC_STATUS1_RSLT(r)   (r & 0xf)
 #define USBC_RSLT_NOTHING  0
@@ -79,11 +94,44 @@
 USBC_IRQ2_RX_HR | USBC_IRQ2_RX_CR | \
 USBC_IRQ2_TX_SUCCESS | USBC_IRQ2_TX_FAIL)
 
+#define USBC_PD_CFG1_ID_FILL   BIT(7)
+
+#define USBC_PD_CFG2_SOP_RXBIT(0)
+
+#define USBC_PD_CFG3_SR_SOP2   (BIT(7) | BIT(6))
+#define USBC_PD_CFG3_SR_SOP1   (BIT(5) | BIT(4))
+#define USBC_PD_CFG3_SR_SOP0   (BIT(3) | BIT(2))
+#define USBC_PD_CFG3_DATAROLE  BIT(1)
+#define USBC_PD_CFG3_PWRROLE   BIT(0)
+
+#define USBC_TX_CMD_TXBUF_RDY  BIT(0)
+#define USBC_TX_CMD_TX_START   BIT(1)
+#define USBC_TX_CMD_TXBUF_CMD(r)   ((r >> 5) & 0x7)
+
+#define USBC_TX_INFO_TX_SOP(BIT(0) | BIT(1) | BIT(2))
+#define USBC_TX_INFO_TX_RETRIES(BIT(3) | BIT(4) | BIT(5))
+
+#define USBC_RX_STATUS_RX_DATA BIT(7)
+#define USBC_RX_STATUS_RX_OVERRUN  BIT(6)
+#define USBC_RX_STATUS_RX_CLEARBIT(0)
+
+#define USBC_PD_STATUS_RX_RSLT(r)  ((r >> 3) & 0x7)
+#define USBC_PD_STATUS_TX_RSLT(r)  (r & 0x7)
+
+#define USBC_RX_INFO_RXBYTES(r)((r >> 3) & 0x1f)
+#define USBC_RX_INFO_RX_SOP(r) (r & 0x7)
+
+#define USBC_PD_RX_BUF_LEN 30
+#define USBC_PD_TX_BUF_LEN 30
+#define USBC_PD_SEND_HR(3 << 5)
+
 struct wcove_typec {
+   int pd_port_num;
struct mutex lock; /* device lock */
struct device *dev;
struct regmap *regmap;
struct typec_port *port;
+   struct pd_sink_port pd_port;
struct typec_capability cap;
struct typec_connection con;
struct typec_partner partner;
@@ -106,6 +154,50 @@ enum wcove_typec_role {
WCOVE_ROLE_DEVICE,
 };
 
+static struct sink_ps profiles[] = {
+
+   {
+   .ps_type = PS_TYPE_FIXED,
+   .ps_fixed = {
+   .voltage_fixed  = 100,  /* 5V/50mV = 100 */
+   .current_default = 90,  /* 900mA/10mA = 90 */
+   .current_max= 90,   /* 900mA/10mA = 90 */
+   },
+
+   },
+
+   {
+   .ps_type = PS_TYPE_FIXED,
+   .ps_fixed = {
+   .voltage_fixed  = 100,
+   .current_default = 300,
+   .current_max= 300,
+   },
+   },
+
+   {
+   .ps_type = PS_TYPE_FIXED,
+   .ps_fixed = {
+   .voltage_fixed  =

Re: [PATCH v2] x86/tsc: Set X86_FEATURE_TSC_RELIABLE to skip refined calibration

2016-10-11 Thread Bin Gao
On Fri, Aug 26, 2016 at 12:14:58PM +0200, Thomas Gleixner wrote:
> On Fri, 26 Aug 2016, Thomas Gleixner wrote:
> > On Thu, 25 Aug 2016, Bin Gao wrote:
> > > On Wed, Aug 24, 2016 at 10:51:20AM +0200, Thomas Gleixner wrote:
> > > > On Tue, 16 Aug 2016, Bin Gao wrote:
> > > > > On some newer Intel x86 processors/SoCs the TSC frequency can be 
> > > > > directly
> > > > > calculated by factors read from specific MSR registers or from a cpuid
> > > > > leaf (0x15). TSC frequency calculated by native msr/cpuid is 
> > > > > absolutely
> > > > > accurate so we should always skip calibrating TSC aginst another 
> > > > > clock,
> > > > > e.g. PIT, HPET, etc. So we want to skip the refined calibration by 
> > > > > setting
> > > > > the X86_FEATURE_TSC_RELIABLE flag. Existing code setting the flag by
> > > > > set_cpu_cap() doesn't work as the flag is cleared later in 
> > > > > identify_cpu().
> > > > > A cpu caps flag is not cleared only if it's set by 
> > > > > setup_force_cpu_cap().
> > > > > This patch converted set_cpu_cap() to setup_force_cpu_cap() to ensure
> > > > > refined calibration is skipped.
> > > > > 
> > > > > We had a test on Intel CherryTrail platform: the 24 hours time drift 
> > > > > is
> > > > > 3.6 seconds if refined calibration was not skipped while the drift is 
> > > > > less
> > > > > than 0.6 second when refined calibration was skipped.
> > > > > 
> > > > > Correctly setting the X86_FEATURE_TSC_RELIABLE flag also guarantees 
> > > > > TSC is
> > > > > not monitored by timekeeping watchdog because on most of these system 
> > > > > TSC
> > > > > is the only reliable clocksource. HPET, for instance, works but may 
> > > > > not
> > > > > be reliable. So kernel may report a physically reliable TSC is not 
> > > > > reliable
> > > > > just because a physically not reliable HPET is acting as timekeeping
> > > > > watchdog.
> > > > 
> > > > What about non SoC systems where the MSR is available, but we still see 
> > > > that
> > > > cross socket TSC wreckage? This change will prevent the watchdog from
> > > > detecting that.
> > > 
> > > MSR is only available on Intel Atom SoCs. There is no such a multi-socket 
> > > system.
> > 
> > Fair enough.
> 
> Second thoughts. We should seperate the calibration aspect from the reliablity
> aspect.
> 
> If a MSR/CPUID readout provides reliable calibration then this does not tell
> us about the reliablity (i.e. no watchdog required). So having two flags for
> this - and sure you can set both on those SoCs is the proper solution.
> 
> Thanks,
> 
>   tglx


Hi Thomas,

The Linux kernel does think a reliable calibration implies the reliability (i.e.
no watchdog required). I'm posting some code pieces to explain.

X86_FEATURE_TSC_RELIABLE is referred only in two places as shown below.

As you can see from init_tsc_clocksource(), X86_FEATURE_TSC_RELIABLE acts
as a switch to launch the delayed calibration work. The delayed calibration
is skipped if X86_FEATURE_TSC_RELIABLE is set, else not.

In check_system_tsc_reliable(), X86_FEATURE_TSC_RELIABLE helps to set
tsc_clocksource_reliable which in turn enables TSC as a clocksource
watchdog, i.e. watching others instead of being watched by others.

So X86_FEATURE_TSC_RELIABLE really means two things:
1) Calibrated(or directly calculated) result is trustable so delayed
   calibration is skipped.
2) TSC is reliable so clocksource framework won't monitor it, instead
   TSC acts as a watchdog monitoring other clocksources.

X86_FEATURE_TSC_RELIABLE is set also only from two places:
arch/x86/platform/intel-mid/mrfld.c and arch/x86/platform/intel-mid/mrfld.c
which are for Intel Atom SoCs with MSR based TSC frequency calculation.

The patch I'm doing is to set this flag (X86_FEATURE_TSC_RELIABLE) for
another case: Intel processors/SoCs with CPUID based TSC frequency calculation.

arch/x86/kernel/tsc.c:
satic void __init check_system_tsc_reliable(void)
{
.. (lines ignored)

if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE))
/* This flag is used by init_tsc_clocksource(), see below. */
tsc_clocksource_reliable = 1;
}

arch/x86/kernel/tsc.c:
static int __init init_tsc_clocksource(void)
{
.. (lines ignored)

if (tsc_clocksource_reliable)
clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY;

.. (lines ignored)

/*
 * Trust the results of the earlier calibration on systems
 * exporting a reliable TSC.
 */
if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE)) {
clocksource_register_khz(&clocksource_tsc, tsc_khz);
return 0;
}
schedule_delayed_work(&tsc_irqwork, 0);
return 0;
}

Thanks,
Bin



[PATCH 0/4] x86/tsc: add X86_FEATURE_TSC_KNOWN_FREQ flag and hardware related changes

2016-11-15 Thread Bin Gao
This patch series adds X86_FEATURE_TSC_KNOWN_FREQ flag and modifies
Intel Atom SoC related TSC codes to use the new TSC_KNOWN_FREQ flag
and the existed TSC_RELIABLE flag.

Bin Gao (4):
  x86/tsc: add X86_FEATURE_TSC_KNOWN_FREQ flag
  x86/tsc: mark TSC frequency determined by CPUID as known
  x86/tsc: mark Intel ATOM_GOLDMONT TSC reliable
  x86/tsc: set TSC_KNOWN_FREQ and TSC_RELIABLE flags on Intel Atom SoCs

 arch/x86/include/asm/cpufeatures.h  |  1 +
 arch/x86/kernel/tsc.c   | 25 ++---
 arch/x86/kernel/tsc_msr.c   | 18 ++
 arch/x86/platform/intel-mid/mfld.c  |  9 +++--
 arch/x86/platform/intel-mid/mrfld.c |  8 ++--
 5 files changed, 54 insertions(+), 7 deletions(-)

-- 
1.9.1



[PATCH 2/4] x86/tsc: mark TSC frequency determined by CPUID as known

2016-11-15 Thread Bin Gao
Unlike TSC calibration where we determin TSC frequency by another timer
with known frequency, CPUs/SoCs with CPUID leaf 0x15 come with a known
frequency and will report the frequency to software via CPUID
instruction. This hardware provided frequency is the "real" frequency
of TSC so we set the X86_FEATURE_TSC_KNOWN_FREQ flag to skip the whole
software calibration process.

We had a 24 hours test on one of the CPUID 0x15 capable platforms. With
PIT calibrated frequency, we got more than 3 seconds drift whereas with
CPUID determined frequency we only got less than 0.5 second drift. This
makes us believe that we should prefer CPUID determined frequency over
software calibrated frequency.

Signed-off-by: Bin Gao 
---
 arch/x86/kernel/tsc.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 3ba146e..f1a7fb5 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -702,6 +702,13 @@ unsigned long native_calibrate_tsc(void)
}
}
 
+   /*
+* TSC frequency determined by CPUID is a "hardware reported"
+* frequency and is the most accurate one so far we have. This
+* is considered a known frequency.
+*/
+   setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
+
return crystal_khz * ebx_numerator / eax_denominator;
 }
 
-- 
1.9.1



[PATCH 4/4] x86/tsc: set TSC_KNOWN_FREQ and TSC_RELIABLE flags on Intel Atom SoCs

2016-11-15 Thread Bin Gao
TSC on Intel Atom SoCs capable of determining TSC frequency by MSR is
reliable and the frequency is known (because it's provided by HW).
On these platforms PIT/HPET is generally not available so
calibration won't work at all and also TSC is the only reliable
clocksource. So we set both X86_FEATURE_TSC_KNOWN_FREQ and
X86_FEATURE_TSC_RELIABLE flags to make sure the calibration is
skipped and no watchdog on TSC.

Signed-off-by: Bin Gao 
---
 arch/x86/kernel/tsc_msr.c   | 18 ++
 arch/x86/platform/intel-mid/mfld.c  |  9 +++--
 arch/x86/platform/intel-mid/mrfld.c |  8 ++--
 3 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c
index 0fe720d..c0f137c 100644
--- a/arch/x86/kernel/tsc_msr.c
+++ b/arch/x86/kernel/tsc_msr.c
@@ -100,5 +100,23 @@ unsigned long cpu_khz_from_msr(void)
 #ifdef CONFIG_X86_LOCAL_APIC
lapic_timer_frequency = (freq * 1000) / HZ;
 #endif
+
+   /*
+* TSC frequency determined by MSR is always considered "known"
+* because it is reported by HW.
+* Another fact is that on MSR capable platforms, PIT/HPET is
+* generally not available so calibration won't work at all.
+*/
+   setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
+
+   /*
+* Unfortunately there is no a HW way to report TSC is reliable.
+* We were told by silicon design team that TSC on Atom SoCs are
+* always "reliable". TSC is also the only reliable clocksource
+* on these SoCs (HPET is either not present or not functional)
+* so marke TSC reliable to avoid watchdog on it.
+*/
+   setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
+
return res;
 }
diff --git a/arch/x86/platform/intel-mid/mfld.c 
b/arch/x86/platform/intel-mid/mfld.c
index 1eb47b6..e793fe5 100644
--- a/arch/x86/platform/intel-mid/mfld.c
+++ b/arch/x86/platform/intel-mid/mfld.c
@@ -49,8 +49,13 @@ static unsigned long __init mfld_calibrate_tsc(void)
fast_calibrate = ratio * fsb;
pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
lapic_timer_frequency = fsb * 1000 / HZ;
-   /* mark tsc clocksource as reliable */
-   set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
+
+   /*
+* TSC on Intel Atom SoCs is reliable and of known frequency.
+* See tsc_msr.c for details.
+*/
+   setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
+   setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
 
return fast_calibrate;
 }
diff --git a/arch/x86/platform/intel-mid/mrfld.c 
b/arch/x86/platform/intel-mid/mrfld.c
index 59253db..e0607c7 100644
--- a/arch/x86/platform/intel-mid/mrfld.c
+++ b/arch/x86/platform/intel-mid/mrfld.c
@@ -78,8 +78,12 @@ static unsigned long __init tangier_calibrate_tsc(void)
pr_debug("Setting lapic_timer_frequency = %d\n",
lapic_timer_frequency);
 
-   /* mark tsc clocksource as reliable */
-   set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
+   /*
+* TSC on Intel Atom SoCs is reliable and of known frequency.
+* See tsc_msr.c for details.
+*/
+   setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
+   setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
 
return fast_calibrate;
 }
-- 
1.9.1



[PATCH 3/4] x86/tsc: mark Intel ATOM_GOLDMONT TSC reliable

2016-11-15 Thread Bin Gao
On Intel GOLDMONT Atom SoC TSC is the only reliable clocksource.
We mark TSC reliable to avoid watchdog on it.

Signed-off-by: Bin Gao 
---
 arch/x86/kernel/tsc.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index f1a7fb5..354b302 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -709,6 +709,13 @@ unsigned long native_calibrate_tsc(void)
 */
setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
 
+   /*
+* For Atom SoCs TSC is the only reliable clocksource.
+* Mark TSC reliable so no watchdog on it.
+*/
+   if (boot_cpu_data.x86_model == INTEL_FAM6_ATOM_GOLDMONT)
+   setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
+
return crystal_khz * ebx_numerator / eax_denominator;
 }
 
-- 
1.9.1



[PATCH 1/4] x86/tsc: add X86_FEATURE_TSC_KNOWN_FREQ flag

2016-11-15 Thread Bin Gao
The X86_FEATURE_TSC_RELIABLE flag in Linux kernel implies both reliable
(at runtime) and trustable (at calibration). But reliable running and
trustable calibration are logically irrelevant. Per Thomas Gleixner's
suggestion we would like to split this flag into two separate flags:
X86_FEATURE_TSC_RELIABLE - running reliably
X86_FEATURE_TSC_KNOWN_FREQ - frequency is known (no calibration required)
These two flags allow Linux kernel to act differently based on
processor/SoC's capability, i.e. no watchdog on TSC if TSC is reliable,
and no calibration if TSC frequency is known.

Current Linux kernel already gurantees calibration is skipped for
processors that can report TSC frequency by CPUID or MSR. However, the
delayed calibration is still not skipped for these CPUID/MSR capable
processors. The new flag X86_FEATURE_TSC_KNOWN_FREQ added by this patch
will gurantee the delayed calibration is skipped.

Signed-off-by: Bin Gao 
---
 arch/x86/include/asm/cpufeatures.h |  1 +
 arch/x86/kernel/tsc.c  | 11 ---
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/arch/x86/include/asm/cpufeatures.h 
b/arch/x86/include/asm/cpufeatures.h
index a396292..7f6a5f8 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -106,6 +106,7 @@
 #define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */
 #define X86_FEATURE_EAGER_FPU  ( 3*32+29) /* "eagerfpu" Non lazy FPU restore */
 #define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state 
*/
+#define X86_FEATURE_TSC_KNOWN_FREQ ( 3*32+31) /* TSC has known frequency */
 
 /* Intel-defined CPU features, CPUID level 0x0001 (ecx), word 4 */
 #define X86_FEATURE_XMM3   ( 4*32+ 0) /* "pni" SSE-3 */
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 46b2f41..3ba146e 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -1283,10 +1283,15 @@ static int __init init_tsc_clocksource(void)
clocksource_tsc.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
 
/*
-* Trust the results of the earlier calibration on systems
-* exporting a reliable TSC.
+* When TSC frequency is known (generally got by MSR or CPUID), we skip
+* the refined calibration and directly register it as a clocksource.
+*
+* We still keep the TSC_RELIABLE flag here to avoid regression -
+* it will be removed after all the conversion for other code paths
+* connected to this flag is done.
 */
-   if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE)) {
+   if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE) ||
+   boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ)) {
clocksource_register_khz(&clocksource_tsc, tsc_khz);
return 0;
}
-- 
1.9.1



Re: Re: [PATCH 1/2] x86/tsc: add X86_FEATURE_TSC_KNOWN_FREQ flag

2016-11-10 Thread Bin Gao
> > --- a/arch/x86/kernel/tsc.c
> > +++ b/arch/x86/kernel/tsc.c
> > @@ -1283,10 +1283,10 @@ static int __init init_tsc_clocksource(void)
> > clocksource_tsc.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
> >  
> > /*
> > -* Trust the results of the earlier calibration on systems
> > -* exporting a reliable TSC.
> > +* When TSC frequency is known (generally got by MSR or CPUID), we skip
> > +* the refined calibration and directly register it as a clocksource.
> >  */
> > -   if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE)) {
> > +   if (boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ)) {
> 
> This causes a regression, because with only this patch applied the 
> architectures which use the reliable flag for this today are not longer 
> taking this path.
> 
> The proper thing to do here is to make this:
> 
>   if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE) ||
>   boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ)) {
> 
> and remove the RELIABLE flag ckeck after the existing users are converted.

I Will fix this in next revision.
 
> Thanks,
> 
>   tglx
> 


Re: Re: [PATCH 2/2] x86: use KNOWN_FREQ and RELIABLE TSC flags on certain processors/SoCs

2016-11-10 Thread Bin Gao
> > @@ -702,6 +702,15 @@ unsigned long native_calibrate_tsc(void)
> > }
> > }
> >  
> > +   setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
> 
> I can understand the one below, but this one changes existing behaviour w/o 
> explaining why this is correct and desired. If at all then this wants to be a 
> seperate patch and not just mingled in your goldmont update.

native_calibrate_tsc() implements determining TSC frequency via CPUID.
The purpose to add X86_FEATURE_TSC_KNOWN_FREQ flag is exactly for this case:
TSC frequency determined via CPUID or MSR are always correct and the whole
calibration should be skipped.

I will create a seperate patch for this to ensure it's not confusing with
the MSR related change below.

> 
> > +   /*
> > +* For Atom SoCs TSC is the only reliable clocksource.
> > +* Mark TSC reliable so no watchdog on it.
> > +*/
> > +   if (boot_cpu_data.x86_model == INTEL_FAM6_ATOM_GOLDMONT)
> > +   setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
> > +
> > return crystal_khz * ebx_numerator / eax_denominator;  }
> >  
> > diff --git a/arch/x86/kernel/tsc_msr.c b/arch/x86/kernel/tsc_msr.c 
> > index 0fe720d..d6aa75a 100644
> > --- a/arch/x86/kernel/tsc_msr.c
> > +++ b/arch/x86/kernel/tsc_msr.c
> > @@ -100,5 +100,9 @@ unsigned long cpu_khz_from_msr(void)  #ifdef 
> > CONFIG_X86_LOCAL_APIC
> > lapic_timer_frequency = (freq * 1000) / HZ;  #endif
> > +
> > +   setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
> > +   setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
> 
> Why is this automatically reliable and of known frequency?

As I said above, TSC frequency determined by CPUID or MSR is always considered
"known" because it is reported by HW.
Regarding the reliable, unfortunately however, there is no a HW way to report
it. We were told by silicon design team it's "reliable".

> 
> This evades the long term TSC calibration and also disables the watchdog, 
> which might break stuff left and right.
> 
> Please makes these changes one by one and explain why they are correct on 
> their own, preferrably with some substantial backfrom from the hw folks.

Yes we confirmed with HW folks. TSC count is guaranteed to monotonically
increase at the fixed frequency even during S3/S0i3 state on these platforms.
This change will be seperate from CPUID related change in next revision.

> 
> Thanks,
> 
>   tglx
> 
> 


  1   2   >