* Re: [PATCH v10 6/7] x86/arch_prctl: Add ARCH_[GET|SET]_CPUID
From: Borislav Petkov @ 2016-11-09 13:12 UTC (permalink / raw)
To: Kyle Huey
Cc: Robert O'Callahan, Thomas Gleixner, Andy Lutomirski,
Ingo Molnar, H. Peter Anvin, x86, Paolo Bonzini,
Radim Krčmář, Jeff Dike, Richard Weinberger,
Alexander Viro, Shuah Khan, Dave Hansen, Peter Zijlstra,
Boris Ostrovsky, Len Brown, Rafael J. Wysocki, Dmitry Safonov,
David Matlack, linux-kernel, user-mode-linux-devel,
user-mode-linux-user, linux-fsdevel, linux-kselftest, kvm
In-Reply-To: <20161108183956.4521-7-khuey@kylehuey.com>
On Tue, Nov 08, 2016 at 10:39:55AM -0800, Kyle Huey wrote:
> Intel supports faulting on the CPUID instruction beginning with Ivy Bridge.
> When enabled, the processor will fault on attempts to execute the CPUID
> instruction with CPL>0. Exposing this feature to userspace will allow a
> ptracer to trap and emulate the CPUID instruction.
>
> When supported, this feature is controlled by toggling bit 0 of
> MSR_MISC_FEATURES_ENABLES. It is documented in detail in Section 2.3.2 of
> http://www.intel.com/content/dam/www/public/us/en/documents/application-notes/virtualization-technology-flexmigration-application-note.pdf
>
> Implement a new pair of arch_prctls, available on both x86-32 and x86-64.
>
> ARCH_GET_CPUID: Returns the current CPUID faulting state, either
> ARCH_CPUID_ENABLE or ARCH_CPUID_SIGSEGV. arg2 must be 0.
>
> ARCH_SET_CPUID: Set the CPUID faulting state to arg2, which must be either
> ARCH_CPUID_ENABLE or ARCH_CPUID_SIGSEGV. Returns EINVAL if arg2 is
> another value or CPUID faulting is not supported on this system.
>
> The state of the CPUID faulting flag is propagated across forks, but reset
> upon exec.
>
> Signed-off-by: Kyle Huey <khuey@kylehuey.com>
> ---
...
> diff --git a/tools/testing/selftests/x86/cpuid-fault.c b/tools/testing/selftests/x86/cpuid-fault.c
> new file mode 100644
> index 0000000..65419de
> --- /dev/null
> +++ b/tools/testing/selftests/x86/cpuid-fault.c
> @@ -0,0 +1,250 @@
> +
> +/*
> + * Tests for arch_prctl(ARCH_GET_CPUID, ...) / arch_prctl(ARCH_SET_CPUID, ...)
> + *
> + * Basic test to test behaviour of ARCH_GET_CPUID and ARCH_SET_CPUID
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +#include <signal.h>
> +#include <inttypes.h>
> +#include <cpuid.h>
> +#include <err.h>
> +#include <errno.h>
> +#include <sys/wait.h>
> +
> +#include <sys/prctl.h>
> +#include <linux/prctl.h>
> +
> +/*
> +#define ARCH_GET_CPUID 0x1005
> +#define ARCH_SET_CPUID 0x1006
> +#define ARCH_CPUID_ENABLE 1
> +#define ARCH_CPUID_SIGSEGV 2
> +#ifdef __x86_64__
> +#define SYS_arch_prctl 158
> +#else
> +#define SYS_arch_prctl 385
> +#endif
> +*/
> +
> +const char *cpuid_names[] = {
> + [0] = "[not set]",
> + [ARCH_CPUID_ENABLE] = "ARCH_CPUID_ENABLE",
> + [ARCH_CPUID_SIGSEGV] = "ARCH_CPUID_SIGSEGV",
> +};
> +
> +int arch_prctl(int code, unsigned long arg2)
> +{
> + return syscall(SYS_arch_prctl, code, arg2);
> +}
> +
> +int cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx,
> + unsigned int *edx)
> +{
> + return __get_cpuid(0, eax, ebx, ecx, edx);
> +}
> +
> +int do_child_exec_test(int eax, int ebx, int ecx, int edx)
> +{
> + int cpuid_val = 0, child = 0, status = 0;
> +
> + printf("arch_prctl(ARCH_GET_CPUID); ");
> +
> + cpuid_val = arch_prctl(ARCH_GET_CPUID, 0);
> + if (cpuid_val < 0)
> + errx(1, "ARCH_GET_CPUID fails now, but not before?");
> +
> + printf("cpuid_val == %s\n", cpuid_names[cpuid_val]);
> + if (cpuid_val != ARCH_CPUID_SIGSEGV)
> + errx(1, "How did cpuid get re-enabled on fork?");
> +
> + if ((child = fork()) == 0) {
ERROR: do not use assignment in if condition
#513: FILE: tools/testing/selftests/x86/cpuid-fault.c:64:
+ if ((child = fork()) == 0) {
There are more in that file.
--
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
--
^ permalink raw reply
* Re: [PATCH 0/4] perf tools: Assorted fixes for hierarchy mode
From: Arnaldo Carvalho de Melo @ 2016-11-09 13:11 UTC (permalink / raw)
To: Markus Trippelsdorf
Cc: Namhyung Kim, Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML
In-Reply-To: <20161108132117.GA14552@x4>
Em Tue, Nov 08, 2016 at 02:21:17PM +0100, Markus Trippelsdorf escreveu:
> On 2016.11.08 at 22:08 +0900, Namhyung Kim wrote:
> > Hello,
> >
> > This patches fix problems in hierarchy output Markus reported some
> > time ago. The code is available on the 'perf/hierarchy-fix-v1' branch
> > in my tree:
> >
> > git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git
> >
> > Any feedbacks are welcomed.
>
> It looks perfect now. Many thanks for your fixes.
Ok, I'll take that as a Tested-by: Markus, ok?
- Arnaldo
^ permalink raw reply
* Re: [PATCH net-next 2/3] ptp: igb: Use the high resolution frequency method.
From: Richard Cochran @ 2016-11-09 13:11 UTC (permalink / raw)
To: Keller, Jacob E
Cc: netdev@vger.kernel.org, tglx@linutronix.de,
Manfred.Rudigier@omicron.at, ulrik.debie-os@e2big.org,
stefan.sorensen@spectralink.com, davem@davemloft.net,
Kirsher, Jeffrey T, john.stultz@linaro.org,
intel-wired-lan@lists.osuosl.org
In-Reply-To: <1478642533.7545.38.camel@intel.com>
On Tue, Nov 08, 2016 at 10:02:22PM +0000, Keller, Jacob E wrote:
> On Tue, 2016-11-08 at 22:49 +0100, Richard Cochran wrote:
> > - rate = ppb;
> > - rate <<= 26;
> > - rate = div_u64(rate, 1953125);
> > + rate = scaled_ppm;
> > + rate <<= 13;
> > + rate = div_u64(rate, 15625);
>
> I'm curious how you generate the new math here, since this can be
> tricky, and I could use more examples in order to port to some of the
> other drivers implementations. I'm not quit sure how to handle the
> value when the lower 16 bits are fractional.
TL;DR version:
In ptp_clock.c we convert scaled_ppm to ppb like this.
ppb = scaled_ppm * 10^3 * 2^-16
If you already have a working driver that does
regval = ppb * SOMEMATH;
then just substitute
regval = (scaled_ppm * 10^3 * 2^-16) * SOMEMATH;
= (scaled_ppm * 5^3 * 2^-13) * SOMEMATH;
and simplify by combining the 5^3 and 2^-13 constants into SOMEMATH.
Longer explanation:
You have to consider how the frequency adjustment HW works, case by
case. Both the i210 and the phyter have an adjustment register that
holds units of 2^-32 nanoseconds per 8 nanosecond clock period, and so
the rate from adjustment value 1 is (2^-32 / 8).
Then with the old interface, the conversion from "adjustment unit" to
ppb was (2^-32 / 8 * 10^9) or (2^-26 * 5^9). The conversion the other
way needs the inverse, and so the code did (ppb << 26) / 5^9.
With the new interface, the conversion from "adjustment unit" to
scaled_ppm is (2^-32 / 8 * 10^6 * 2^16) or (2^-13 * 5^6). The code
converts the other direction using the inverse, (s_ppm << 13) / 5^6.
HTH,
Richard
^ permalink raw reply
* [ath6kl:pending 25/27] include/linux/soc/qcom/smem_state.h:28:9: error: implicit declaration of function 'ERR_PTR'
From: kbuild test robot @ 2016-11-09 13:11 UTC (permalink / raw)
To: Bjorn Andersson; +Cc: Kalle Valo, kbuild-all, ath10k
[-- Attachment #1: Type: text/plain, Size: 3509 bytes --]
tree: https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git pending
head: 0b28fa7b6a77e1815cb5d34fe5b889ab53c5ca04
commit: d557637809b66bd63a4d4693a11d5c287a6a68c0 [25/27] wcn36xx: Transition driver to SMD client
config: sparc64-allmodconfig (attached as .config)
compiler: sparc64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
git checkout d557637809b66bd63a4d4693a11d5c287a6a68c0
# save the attached .config to linux build tree
make.cross ARCH=sparc64
All errors (new ones prefixed by >>):
In file included from drivers/net/wireless/ath/wcn36xx/dxe.c:26:0:
include/linux/soc/qcom/smem_state.h: In function 'qcom_smem_state_get':
>> include/linux/soc/qcom/smem_state.h:28:9: error: implicit declaration of function 'ERR_PTR' [-Werror=implicit-function-declaration]
return ERR_PTR(-EINVAL);
^~~~~~~
include/linux/soc/qcom/smem_state.h:28:9: warning: return makes pointer from integer without a cast [-Wint-conversion]
return ERR_PTR(-EINVAL);
^~~~~~~~~~~~~~~~
include/linux/soc/qcom/smem_state.h: In function 'qcom_smem_state_register':
include/linux/soc/qcom/smem_state.h:44:9: warning: return makes pointer from integer without a cast [-Wint-conversion]
return ERR_PTR(-EINVAL);
^~~~~~~~~~~~~~~~
In file included from include/linux/rwsem.h:17:0,
from include/linux/mm_types.h:10,
from include/linux/kmemcheck.h:4,
from include/linux/skbuff.h:18,
from include/linux/if_ether.h:23,
from include/net/mac80211.h:20,
from drivers/net/wireless/ath/wcn36xx/wcn36xx.h:23,
from drivers/net/wireless/ath/wcn36xx/dxe.c:27:
include/linux/err.h: At top level:
>> include/linux/err.h:23:35: error: conflicting types for 'ERR_PTR'
static inline void * __must_check ERR_PTR(long error)
^~~~~~~
In file included from drivers/net/wireless/ath/wcn36xx/dxe.c:26:0:
include/linux/soc/qcom/smem_state.h:28:9: note: previous implicit declaration of 'ERR_PTR' was here
return ERR_PTR(-EINVAL);
^~~~~~~
cc1: some warnings being treated as errors
vim +/ERR_PTR +28 include/linux/soc/qcom/smem_state.h
9460ae2f Bjorn Andersson 2015-09-24 22
e8b123e6 Bjorn Andersson 2015-12-24 23 #else
e8b123e6 Bjorn Andersson 2015-12-24 24
e8b123e6 Bjorn Andersson 2015-12-24 25 static inline struct qcom_smem_state *qcom_smem_state_get(struct device *dev,
e8b123e6 Bjorn Andersson 2015-12-24 26 const char *con_id, unsigned *bit)
e8b123e6 Bjorn Andersson 2015-12-24 27 {
e8b123e6 Bjorn Andersson 2015-12-24 @28 return ERR_PTR(-EINVAL);
e8b123e6 Bjorn Andersson 2015-12-24 29 }
e8b123e6 Bjorn Andersson 2015-12-24 30
e8b123e6 Bjorn Andersson 2015-12-24 31 static inline void qcom_smem_state_put(struct qcom_smem_state *state)
:::::: The code at line 28 was first introduced by commit
:::::: e8b123e6008480b2b8d80dae060315d84b79f4bb soc: qcom: smem_state: Add stubs for disabled smem_state
:::::: TO: Bjorn Andersson <bjorn@kryo.se>
:::::: CC: Andy Gross <andy.gross@linaro.org>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 47837 bytes --]
[-- Attachment #3: Type: text/plain, Size: 146 bytes --]
_______________________________________________
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k
^ permalink raw reply
* [alsa-devel] [PATCH 2/9] ALSA: ac97: add an ac97 bus
From: Lars-Peter Clausen @ 2016-11-09 13:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87eg2ly8k6.fsf@belgarion.home>
On 11/08/2016 10:18 PM, Robert Jarzmik wrote:
[...]
>>> +/**
>>> + * struct ac97_controller - The AC97 controller of the AC-Link
>>> + * @ops: the AC97 operations.
>>> + * @controllers: linked list of all existing controllers.
>>> + * @dev: the device providing the AC97 controller.
>>> + * @slots_available: the mask of accessible/scanable codecs.
>>> + * @codecs: the 4 possible AC97 codecs (NULL if none found).
>>> + * @codecs_pdata: platform_data for each codec (NULL if no pdata).
>>> + *
>>> + * This structure is internal to AC97 bus, and should not be used by the
>>> + * controllers themselves, excepting for using @dev.
>>> + */
>>> +struct ac97_controller {
>>> + const struct ac97_controller_ops *ops;
>>> + struct list_head controllers;
>>> + struct device *dev;
>>
>> I'd make the controller itself a struct dev, rather than just having the
>> pointer to the parent. This is more idiomatic and matches what other
>> subsystems do. It has several advantages, you get proper refcounting of your
>> controller structure, the controller gets its own sysfs directory where the
>> CODECs appear as children, you don't need the manual sysfs attribute
>> creation and removal in ac97_controler_{un,}register().
>
> If you mean having "struct device dev" instead of "struct device *dev", it has
> also a drawback : all the legacy platforms have already a probing method, be
> that platform data, device-tree or something else.
>
> I'm a bit converned about the conversion toll. Maybe I've not understood your
> point fully, so please feel free to explain, with an actual example even better.
This would be a struct device that is not bound to a driver, but just acts
as a shell for the controller and places it inside the device hierarchy. You
get reference counting and other management functions as well as a
consistent naming scheme. E.g. you can call the devices ac97c%d (or
something similar) and then call the CODEC ac97c%d.%d.
This is how most frameworks implementing some kind of control bus are
structured in the Linux kernel. E.g. take a look at I2C or SPI.
Your controller driver itself is unaffected by this, you still call
snd_ac97_controller_register() from the probe function and so on.
>
>>> + void (*wait)(struct ac97_controller *adrv, int slot);
>>> + void (*init)(struct ac97_controller *adrv, int slot);
>>
>> Neither wait nor init are ever used.
> This is because I've not begun to porting sound/pci/ac97_codec.c into
> sound/ac97.
Ok, makes sense. But maybe just leave them out for now and add them when
they are used.
[...]
>>> + ret = sysfs_create_link(&codec->dev.kobj, &ac97_ctrl->dev->kobj,
>>> + "ac97_controller");
>>
>> Since the CODEC is a child of the controller this should not be necessary as
>> this just points one directory up. It's like `ln -s .. parent`
> This creates :
> /sys/bus/ac97/devices/pxa2xx-ac97\:0/ac97_controller
>
> Of course as you pointed out, it's a 'ln -s .. parent' like link, but it seems
> to me very unfriendly to have :
> - /sys/bus/ac97/devices/pxa2xx-ac97\:0/../ac97_operations
> - while /sys/bus/ac97/devices/ac97_operations doesn't exist (obviously)
>
> Mmm, I don't know for this one, my mind is not set, it's a bit hard to tell if
> it's only an unecessary link bringing "comfort", or something usefull.
It is additional ABI and we do not have this for any other bus either (e.g.
you don't see a backlink for a I2C or SPI device to the parent). In my
opinion for the sake of keeping things consistent and simple we should not
add this.
>>
>>> + if (ret)
>>> + goto err_unregister_device;
>>> +
>>> + return 0;
>>> +err_unregister_device:
>>> + put_device(&codec->dev);
>>> +err_free_codec:
>>> + kfree(codec);
>>
>> Since the struct is reference counted, the freeing is done in the release
>> callback and this leads to a double free.
> A yes in the "goto err_unregister_device" case right, while it's necessary in
> the "goto err_free_codec" case ... I need to rework that a bit.
It should use put_device() in both cases, check the the device_register()
documentation. It says that put_device() must be used, even if
device_register() fails.
>
>>> +int snd_ac97_codec_driver_register(struct ac97_codec_driver *drv)
>>> +{
>>> + int ret;
>>> +
>>> + drv->driver.bus = &ac97_bus_type;
>>> +
>>> + ret = driver_register(&drv->driver);
>>> + if (!ret)
>>> + ac97_rescan_all_controllers();
>>
>> Rescanning the bus when a new codec driver is registered should not be
>> neccessary. The bus is scanned once when the controller is registered, this
>> creates the device. The device driver core will take care of binding the
>> device to the driver, if the driver is registered after thed evice.
> That's because you suppose the initial scanning found all the ac97 codecs.
> But that's an incomplete vision as a codec might be powered off at that time and
> not seen by the first scanning, while the new scanning will discover it.
But why would the device become suddenly visible when the driver is
registered. This seems to be an as arbitrary point in time as any other.
Also consider that when you build a driver as a module, the module will
typically only be auto-loaded after the device has been detected, based on
the device ID. On the other hand, if the driver is built-in driver
registration will happen either before or shortly after the controller
registration.
If there is the expectation that the AC97 CODEC might randomly appear on the
bus, the core should periodically scan the bus.
[...]
>>> + ac97_ctrl->ops->warm_reset(ac97_ctrl);
>>> + return len;
>>> +}
>>> +static DEVICE_ATTR_WO(warm_reset);
>>> +
>>> +static struct attribute *ac97_controller_device_attrs[] = {
>>> + &dev_attr_cold_reset.attr,
>>> + &dev_attr_warm_reset.attr,
>>> + NULL
>>> +};
>>
>> This adds new userspace ABI that is not documented at the moment.
> Very true. And as all userspace interface, it needs to be discussed. If nobody
> complains, I'll add the documentation for next patch round.
>>
>>> +int snd_ac97_controller_register(const struct ac97_controller_ops *ops,
>>> + struct device *dev,
>>> + unsigned short slots_available,
>>> + void **codecs_pdata)
>>
>> In my opinion this should return a handle to a ac97 controller which can
>> then be passed to snd_ac97_controller_unregister(). This is in my opinion
>> the better approach rather than looking up the controller by parent device.
> This is another "legacy drivers" issue.
>
> The legacy driver (the one probed by platform_data or devicetree) doesn't
> necessarily have a private structure to store this ac97_controller pointer.
I might be missing something, but I'm not convinced by this. Can you point
me to such a legacy driver where you think this would not work?
^ permalink raw reply
* Re: [alsa-devel] [PATCH 2/9] ALSA: ac97: add an ac97 bus
From: Lars-Peter Clausen @ 2016-11-09 13:11 UTC (permalink / raw)
To: Robert Jarzmik
Cc: Dmitry Torokhov, Lee Jones, Sebastian Reichel, Jaroslav Kysela,
Takashi Iwai, Daniel Mack, Haojian Zhuang, Liam Girdwood,
Mark Brown, alsa-devel, linux-pm, patches, linux-kernel,
linux-input, linux-arm-kernel
In-Reply-To: <87eg2ly8k6.fsf@belgarion.home>
On 11/08/2016 10:18 PM, Robert Jarzmik wrote:
[...]
>>> +/**
>>> + * struct ac97_controller - The AC97 controller of the AC-Link
>>> + * @ops: the AC97 operations.
>>> + * @controllers: linked list of all existing controllers.
>>> + * @dev: the device providing the AC97 controller.
>>> + * @slots_available: the mask of accessible/scanable codecs.
>>> + * @codecs: the 4 possible AC97 codecs (NULL if none found).
>>> + * @codecs_pdata: platform_data for each codec (NULL if no pdata).
>>> + *
>>> + * This structure is internal to AC97 bus, and should not be used by the
>>> + * controllers themselves, excepting for using @dev.
>>> + */
>>> +struct ac97_controller {
>>> + const struct ac97_controller_ops *ops;
>>> + struct list_head controllers;
>>> + struct device *dev;
>>
>> I'd make the controller itself a struct dev, rather than just having the
>> pointer to the parent. This is more idiomatic and matches what other
>> subsystems do. It has several advantages, you get proper refcounting of your
>> controller structure, the controller gets its own sysfs directory where the
>> CODECs appear as children, you don't need the manual sysfs attribute
>> creation and removal in ac97_controler_{un,}register().
>
> If you mean having "struct device dev" instead of "struct device *dev", it has
> also a drawback : all the legacy platforms have already a probing method, be
> that platform data, device-tree or something else.
>
> I'm a bit converned about the conversion toll. Maybe I've not understood your
> point fully, so please feel free to explain, with an actual example even better.
This would be a struct device that is not bound to a driver, but just acts
as a shell for the controller and places it inside the device hierarchy. You
get reference counting and other management functions as well as a
consistent naming scheme. E.g. you can call the devices ac97c%d (or
something similar) and then call the CODEC ac97c%d.%d.
This is how most frameworks implementing some kind of control bus are
structured in the Linux kernel. E.g. take a look at I2C or SPI.
Your controller driver itself is unaffected by this, you still call
snd_ac97_controller_register() from the probe function and so on.
>
>>> + void (*wait)(struct ac97_controller *adrv, int slot);
>>> + void (*init)(struct ac97_controller *adrv, int slot);
>>
>> Neither wait nor init are ever used.
> This is because I've not begun to porting sound/pci/ac97_codec.c into
> sound/ac97.
Ok, makes sense. But maybe just leave them out for now and add them when
they are used.
[...]
>>> + ret = sysfs_create_link(&codec->dev.kobj, &ac97_ctrl->dev->kobj,
>>> + "ac97_controller");
>>
>> Since the CODEC is a child of the controller this should not be necessary as
>> this just points one directory up. It's like `ln -s .. parent`
> This creates :
> /sys/bus/ac97/devices/pxa2xx-ac97\:0/ac97_controller
>
> Of course as you pointed out, it's a 'ln -s .. parent' like link, but it seems
> to me very unfriendly to have :
> - /sys/bus/ac97/devices/pxa2xx-ac97\:0/../ac97_operations
> - while /sys/bus/ac97/devices/ac97_operations doesn't exist (obviously)
>
> Mmm, I don't know for this one, my mind is not set, it's a bit hard to tell if
> it's only an unecessary link bringing "comfort", or something usefull.
It is additional ABI and we do not have this for any other bus either (e.g.
you don't see a backlink for a I2C or SPI device to the parent). In my
opinion for the sake of keeping things consistent and simple we should not
add this.
>>
>>> + if (ret)
>>> + goto err_unregister_device;
>>> +
>>> + return 0;
>>> +err_unregister_device:
>>> + put_device(&codec->dev);
>>> +err_free_codec:
>>> + kfree(codec);
>>
>> Since the struct is reference counted, the freeing is done in the release
>> callback and this leads to a double free.
> A yes in the "goto err_unregister_device" case right, while it's necessary in
> the "goto err_free_codec" case ... I need to rework that a bit.
It should use put_device() in both cases, check the the device_register()
documentation. It says that put_device() must be used, even if
device_register() fails.
>
>>> +int snd_ac97_codec_driver_register(struct ac97_codec_driver *drv)
>>> +{
>>> + int ret;
>>> +
>>> + drv->driver.bus = &ac97_bus_type;
>>> +
>>> + ret = driver_register(&drv->driver);
>>> + if (!ret)
>>> + ac97_rescan_all_controllers();
>>
>> Rescanning the bus when a new codec driver is registered should not be
>> neccessary. The bus is scanned once when the controller is registered, this
>> creates the device. The device driver core will take care of binding the
>> device to the driver, if the driver is registered after thed evice.
> That's because you suppose the initial scanning found all the ac97 codecs.
> But that's an incomplete vision as a codec might be powered off at that time and
> not seen by the first scanning, while the new scanning will discover it.
But why would the device become suddenly visible when the driver is
registered. This seems to be an as arbitrary point in time as any other.
Also consider that when you build a driver as a module, the module will
typically only be auto-loaded after the device has been detected, based on
the device ID. On the other hand, if the driver is built-in driver
registration will happen either before or shortly after the controller
registration.
If there is the expectation that the AC97 CODEC might randomly appear on the
bus, the core should periodically scan the bus.
[...]
>>> + ac97_ctrl->ops->warm_reset(ac97_ctrl);
>>> + return len;
>>> +}
>>> +static DEVICE_ATTR_WO(warm_reset);
>>> +
>>> +static struct attribute *ac97_controller_device_attrs[] = {
>>> + &dev_attr_cold_reset.attr,
>>> + &dev_attr_warm_reset.attr,
>>> + NULL
>>> +};
>>
>> This adds new userspace ABI that is not documented at the moment.
> Very true. And as all userspace interface, it needs to be discussed. If nobody
> complains, I'll add the documentation for next patch round.
>>
>>> +int snd_ac97_controller_register(const struct ac97_controller_ops *ops,
>>> + struct device *dev,
>>> + unsigned short slots_available,
>>> + void **codecs_pdata)
>>
>> In my opinion this should return a handle to a ac97 controller which can
>> then be passed to snd_ac97_controller_unregister(). This is in my opinion
>> the better approach rather than looking up the controller by parent device.
> This is another "legacy drivers" issue.
>
> The legacy driver (the one probed by platform_data or devicetree) doesn't
> necessarily have a private structure to store this ac97_controller pointer.
I might be missing something, but I'm not convinced by this. Can you point
me to such a legacy driver where you think this would not work?
^ permalink raw reply
* [Intel-wired-lan] [PATCH net-next 2/3] ptp: igb: Use the high resolution frequency method.
From: Richard Cochran @ 2016-11-09 13:11 UTC (permalink / raw)
To: intel-wired-lan
In-Reply-To: <1478642533.7545.38.camel@intel.com>
On Tue, Nov 08, 2016 at 10:02:22PM +0000, Keller, Jacob E wrote:
> On Tue, 2016-11-08 at 22:49 +0100, Richard Cochran wrote:
> > - rate = ppb;
> > - rate <<= 26;
> > - rate = div_u64(rate, 1953125);
> > + rate = scaled_ppm;
> > + rate <<= 13;
> > + rate = div_u64(rate, 15625);
>
> I'm curious how you generate the new math here, since this can be
> tricky, and I could use more examples in order to port to some of the
> other drivers implementations. I'm not quit sure how to handle the
> value when the lower 16 bits are fractional.
TL;DR version:
In ptp_clock.c we convert scaled_ppm to ppb like this.
ppb = scaled_ppm * 10^3 * 2^-16
If you already have a working driver that does
regval = ppb * SOMEMATH;
then just substitute
regval = (scaled_ppm * 10^3 * 2^-16) * SOMEMATH;
= (scaled_ppm * 5^3 * 2^-13) * SOMEMATH;
and simplify by combining the 5^3 and 2^-13 constants into SOMEMATH.
Longer explanation:
You have to consider how the frequency adjustment HW works, case by
case. Both the i210 and the phyter have an adjustment register that
holds units of 2^-32 nanoseconds per 8 nanosecond clock period, and so
the rate from adjustment value 1 is (2^-32 / 8).
Then with the old interface, the conversion from "adjustment unit" to
ppb was (2^-32 / 8 * 10^9) or (2^-26 * 5^9). The conversion the other
way needs the inverse, and so the code did (ppb << 26) / 5^9.
With the new interface, the conversion from "adjustment unit" to
scaled_ppm is (2^-32 / 8 * 10^6 * 2^16) or (2^-13 * 5^6). The code
converts the other direction using the inverse, (s_ppm << 13) / 5^6.
HTH,
Richard
^ permalink raw reply
* Re: [PATCH 0/4] perf tools: Assorted fixes for hierarchy mode
From: Arnaldo Carvalho de Melo @ 2016-11-09 13:10 UTC (permalink / raw)
To: Markus Trippelsdorf
Cc: Namhyung Kim, Ingo Molnar, Peter Zijlstra, Jiri Olsa, LKML
In-Reply-To: <20161108151023.GC14552@x4>
Em Tue, Nov 08, 2016 at 04:10:23PM +0100, Markus Trippelsdorf escreveu:
> On 2016.11.09 at 00:05 +0900, Namhyung Kim wrote:
> > On Tue, Nov 8, 2016 at 10:43 PM, Markus Trippelsdorf
> > <markus@trippelsdorf.de> wrote:
> > > On 2016.11.08 at 22:08 +0900, Namhyung Kim wrote:
> > >> This patches fix problems in hierarchy output Markus reported some
> > >> time ago. The code is available on the 'perf/hierarchy-fix-v1' branch
> > >> in my tree:
> > >> git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git
> > >> Any feedbacks are welcomed.
> > > By the way, I hope that:
> > > https://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/commit/?h=perf/core&id=8a06b0be6507f97f3aa92ca814335b8b65fd3de2
> > > doesn't fall through the cracks.
> > What do you mean? It's already in the tip/perf/core so will be merged
> > to the mainline eventually.
> Ok. I was just wondering, because it sits there for two weeks already...
If you think something qualifies for perf/urgent, i.e. to go to a kernel
that is in -rc stage, v4.9-rc4 now, for instance, please point that out
and I'll consider it.
- Arnaldo
^ permalink raw reply
* Re: [PATCH rdma-core 1/7] libhns: Add initial main frame
From: oulijun @ 2016-11-09 13:10 UTC (permalink / raw)
To: Leon Romanovsky, Jason Gunthorpe
Cc: dledford-H+wXaHxf7aLQT0dZR+AlfA,
linux-rdma-u79uwXL29TY76Z2rM5mHXA,
linuxarm-hv44wF8Li93QT0dZR+AlfA
In-Reply-To: <20161108125441.GB27883-2ukJVAZIZ/Y@public.gmane.org>
在 2016/11/8 20:54, Leon Romanovsky 写道:
> On Mon, Nov 07, 2016 at 04:15:32PM -0700, Jason Gunthorpe wrote:
>> On Sat, Oct 29, 2016 at 09:16:25AM +0800, oulijun wrote:
>>
>>> We hope that the only one userspace library file named
>>> libhns-rdmav2.so will be used for the different hardware
>>> version(hip06, hip07, ...), because there are only little change
>>> between their userspace drivers. So we need to distinguish hardware
>>> version.
>>
>> I guess that makes sense, but you still need to be able to parse dt
>> compatible strings that are lists.
>
> IMHO, it can be easily done as follow up patches.
>
Hi, Leon & Jason
We hope that the only one userspace library file named libhns-rdmav2.so will be used for the different hardware version(hip06, hip07, ...),
because there are only little change between their userspace drivers. So we need to distinguish hardware version.
We can't distinguish them if only matching driver name "hns_roce".
It will be matched it when appeared the second hard version, the code will be fixed as follows:
firstly, we will add a hca_table structure:
static struct {
unsigned int vendor;
unsigned int device;
void *data;
int version;
} hca_table[] = {
{PCI_VENDOR_ID_HISILICON, 0xA223, &hns_roce_u_hw_v2, HNS_ROCE_HW_VER2},
{PCI_VENDOR_ID_HISILICON, 0xA224, &hns_roce_u_hw_v2, HNS_ROCE_HW_VER2},
{PCI_VENDOR_ID_HISILICON, 0xA225, &hns_roce_u_hw_v2, HNS_ROCE_HW_VER2},
{PCI_VENDOR_ID_HISILICON, 0xA226, &hns_roce_u_hw_v2, HNS_ROCE_HW_VER2},
{PCI_VENDOR_ID_HISILICON, 0xA227, &hns_roce_u_hw_v2, HNS_ROCE_HW_VER2},
{PCI_VENDOR_ID_HISILICON, 0xA22F, &hns_roce_u_hw_v2, HNS_ROCE_HW_VER2},
};
second, we will distinguish with it by hca_table[]:
if (ibv_read_sysfs_file(uverbs_sys_path, "device/modalias",
value, sizeof(value)) > 0)
for (i = 0; i < sizeof(acpi_table) / sizeof(acpi_table[0]); ++i)
if (!strcmp(value, acpi_table[i].hid)) {
u_hw = acpi_table[i].data;
hw_version = acpi_table[i].version;
goto found;
}
if (ibv_read_sysfs_file(uverbs_sys_path, "device/of_node/compatible",
value, sizeof(value)) > 0)
for (i = 0; i < sizeof(dt_table) / sizeof(dt_table[0]); ++i)
if (!strcmp(value, dt_table[i].compatible)) {
u_hw = dt_table[i].data;
hw_version = dt_table[i].version;
goto found;
}
if (ibv_read_sysfs_file(uverbs_sys_path, "device/device", value,
sizeof(value)) < 0)
return NULL;
sscanf(value, "%i", &vendor);
if (ibv_read_sysfs_file(uverbs_sys_path, "device/vendor", value,
sizeof(value)) < 0)
return NULL;
sscanf(value, "%i", &vendor);
for (i = 0; i < sizeof(hca_table) / sizeof(hca_table[0]); ++i)
if (vendor == hca_table[i].vendor &&
device == hca_table[i].device)
goto found;
for using the path "device/of_node/compatible" when startup by DT method with hip06,
the content of compatible can only match with the device id and name in the hns-roce.ko:
static const struct of_device_id hns_roce_of_match[] = {
{ .compatible = "hisilicon,hns-roce-v1", .data = &hns_roce_hw_v1, },
{},
};
hence, we think that it will be distinguished by found the string("hisilicon, hns-roce-v1") in
/../../../device/of_node/compatible
When the userspace library of hns support hip07 or hip 08, the so file is still libhns-rdmav2.so and
will be used simultaneously for hip06 and hip07 or hip08 etc.
Lijun Ou
>>
>> Jason
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
>> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* RE: [PATCH net] r8152: Fix broken RX checksums.
From: Hayes Wang @ 2016-11-09 13:09 UTC (permalink / raw)
To: Mark Lord, David Miller
Cc: nic_swsd, netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <201611041425.uA4EPwCw018176@rtits1.realtek.com>
Mark Lord [mailto:mlord@pobox.com]
> Sent: Friday, November 04, 2016 9:50 PM
[...]
> Yeah, the device or driver is definitely getting confused with rx_desc structures.
> I added code to check for unlikely rx_desc values, and it found this for starters:
>
> rx_desc: 00480801 00480401 00480001 0048fc00 0048f800 0048f400
> pkt_len=2045
> rx_data: 00 f0 48 00 00 ec 48 00 00 e8 48 00 00 e4 48 00 00 e0 48 00 00 dc 48 00
> 00 d8 48 00 00 d4 48 00
> rx_data: 00 d0 48 00 00 cc 48 00 00 c8 48 00 00 c4 48 00 00 c0 48 00 00 bc 48 00
> 00 b8 48 00 00 b4 48 00
> rx_data: 00 b0 48 00 00 ac 48 00 00 01 00 00 81 ed 00 00 00 01 00 00 00 00 00 00
> 00 00 00 02 4d ac 00 00
> rx_data: 10 00 ff ff ff ff 00 00 01 28 83 d6 ff 6d 00 20 25 b1 58 1b 68 ff 00 05 20 01
> 56 41 17 35 00 00
> ...
>
> The MTU/MRU on this link is the standard 1500 bytes, so a pkt_len of 2045 isn't
> valid here.
> And the rx_desc values look an awful lot like the rx_data values that follow it.
>
> There's definitely more broken here than just TCP RX checksums.
I don't think it is the issue of our hw. If it happens, windows or
other OS may have problems, too. It is like the memory issue described
in commit 990c9b347245("Merge branch 'r8152-fixes'"). It seems that
the data in memory is not same with the one from the device.
Besides, I test the raspberry pi with RTL8152. However, I don't find
any checksum issue for TCP. I try to copy a large file and md5sum it
through NFS. It works fine.
Best Regards,
Hayes
^ permalink raw reply
* Re: [PATCH 0/6] thunderbolt: Introducing Thunderbolt(TM) networking
From: Lukas Wunner @ 2016-11-09 13:11 UTC (permalink / raw)
To: Andreas Noever
Cc: Levy, Amir (Jer), gregkh@linuxfoundation.org, bhelgaas@google.com,
linux-pci@vger.kernel.org, Jamet, Michael, Alloun, Dan,
Westerberg, Mika, Svahn, Kai, Shevchenko, Andriy, Winkler, Tomas
In-Reply-To: <CAMxnaaUz8nhqVc8ubaOVhSjkcwMUUYZjn5NvJ=mTkGk_SvD8Qg@mail.gmail.com>
On Wed, May 25, 2016 at 01:24:43AM +0200, Andreas Noever wrote:
> - Is it possible to use the ICM on Apple hardware?
Found this by accident:
On Macs introduced 2015 (MBP11,4, MBP11,5, MBP12,1, iMac17,1, ...)
the DSDT contains AML code which appears to enable ICM for
\_OSI("Windows 2012"), i.e. Windows 8 but not 7, presumably for BootCamp.
Grab an acpidump of an MBP11,4 here and search for ICM:
https://bugzilla.kernel.org/attachment.cgi?id=207701
There are two ICM-related GPEs, 0x10 and 0x14.
Best regards,
Lukas
^ permalink raw reply
* Re: [PATCH] examples/l3fwd: force CRC stripping for i40evf
From: Björn Töpel @ 2016-11-09 13:09 UTC (permalink / raw)
To: Zhang, Helin, Ananyev, Konstantin, dev@dpdk.org
Cc: Xu, Qian Q, Yao, Lei A, Wu, Jingjing, thomas.monjalon@6wind.com
In-Reply-To: <F35DEAC7BCE34641BA9FAC6BCA4A12E717F4AED3@SHSMSX103.ccr.corp.intel.com>
Björn/Konstantin wrote:
>> Finally, why doesn't l3fwd have the CRC stripped?
>
> I don’t know any good reason for that for l3fwd or any other sample
> app. I think it is just a 'historical' reason.
Ok! Then I'd suggest changing the l3fwd default to actually *strip* CRC
instead of not doing it. Lei, any comments?
Helin wrote:
> Yes, i40e driver changed a little bit on that according to the
> review comments during implementation, comparing to igb and ixgbe.
> I'd suggest to re-invesitgate if we can do the similar thing in igb
> and ixgbe driver.
Good. Let's do that!
> Any critical issue now? Or just an improvement comments?
Not from my perspective. The issue is that Lei needs some kind of
work-around for l3fwd with i40evf, so I'll let Lei comment on how
critical it is.
Björn
^ permalink raw reply
* [PATCH V2 4/4] soc/tegra: pmc: Make configuration of IO pads in atomic context
From: Laxman Dewangan @ 2016-11-09 13:09 UTC (permalink / raw)
To: thierry.reding, swarren
Cc: gnurou, jonathanh, linux-tegra, linux-kernel, Laxman Dewangan
In-Reply-To: <1478696962-11831-1-git-send-email-ldewangan@nvidia.com>
The IO pad voltage configuration can be done in the regulator
notifier callback which is atomic in nature.
Replace the mutex with spin lock for the locking mechanism.
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
---
Changes from V1:
New in series based on pinctrl driver requirement.
---
drivers/soc/tegra/pmc.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 916a94b..52cd218 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -172,6 +172,7 @@ struct tegra_pmc_soc {
* @lp0_vec_size: size of the LP0 warm boot code
* @powergates_available: Bitmap of available power gates
* @powergates_lock: mutex for power gate register access
+ * @io_pad_lock: Spinlock for IO pad voltage register access
* @plat_subdevs: Platform device for PMC child devices.
*/
struct tegra_pmc {
@@ -199,6 +200,7 @@ struct tegra_pmc {
DECLARE_BITMAP(powergates_available, TEGRA_POWERGATE_MAX);
struct mutex powergates_lock;
+ struct spinlock io_pad_lock;
struct platform_device **plat_subdevs;
};
@@ -1103,7 +1105,7 @@ int tegra_io_pad_set_voltage(enum tegra_io_pad id,
if (pad->voltage == UINT_MAX)
return -ENOTSUPP;
- mutex_lock(&pmc->powergates_lock);
+ spin_lock(&pmc->io_pad_lock);
/* write-enable PMC_PWR_DET_VALUE[pad->voltage] */
value = tegra_pmc_readl(PMC_PWR_DET);
@@ -1120,7 +1122,7 @@ int tegra_io_pad_set_voltage(enum tegra_io_pad id,
tegra_pmc_writel(value, PMC_PWR_DET_VALUE);
- mutex_unlock(&pmc->powergates_lock);
+ spin_unlock(&pmc->io_pad_lock);
usleep_range(100, 250);
@@ -1800,6 +1802,7 @@ static int __init tegra_pmc_early_init(void)
u32 value;
mutex_init(&pmc->powergates_lock);
+ spin_lock_init(&pmc->io_pad_lock);
np = of_find_matching_node_and_match(NULL, tegra_pmc_match, &match);
if (!np) {
--
2.1.4
^ permalink raw reply related
* [PATCH V2 3/4] soc/tegra: pmc: Register PMC child devices as platform device
From: Laxman Dewangan @ 2016-11-09 13:09 UTC (permalink / raw)
To: thierry.reding, swarren
Cc: gnurou, jonathanh, linux-tegra, linux-kernel, Laxman Dewangan
In-Reply-To: <1478696962-11831-1-git-send-email-ldewangan@nvidia.com>
Power Management Controller(PMC) of Tegra does the multiple chip
power management related functionality for internal and IO interfacing.
Some of the functionalities are power gating of IP blocks, IO pads
voltage and power state configuration, system power state configurations,
wakeup controls etc.
Different functionalities of the PMC are provided through different
framework like IO pads control can be provided through pinctrl framework,
IO power control is via misc driver etc. All sub functionalities are
represented as PMC child devices.
Register the PMC child devices as platform device and fill the child
devices table for Tegra124 and Tegra210.
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
---
Changes from V1:
None
---
drivers/soc/tegra/pmc.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 44546bd..916a94b 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -145,6 +145,9 @@ struct tegra_pmc_soc {
const struct tegra_io_pad_soc *io_pads;
unsigned int num_io_pads;
+
+ const char **sub_devs_name;
+ unsigned int num_sub_devs;
};
/**
@@ -169,6 +172,7 @@ struct tegra_pmc_soc {
* @lp0_vec_size: size of the LP0 warm boot code
* @powergates_available: Bitmap of available power gates
* @powergates_lock: mutex for power gate register access
+ * @plat_subdevs: Platform device for PMC child devices.
*/
struct tegra_pmc {
struct device *dev;
@@ -195,6 +199,7 @@ struct tegra_pmc {
DECLARE_BITMAP(powergates_available, TEGRA_POWERGATE_MAX);
struct mutex powergates_lock;
+ struct platform_device **plat_subdevs;
};
static struct tegra_pmc *pmc = &(struct tegra_pmc) {
@@ -1375,6 +1380,43 @@ static void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc)
of_node_put(np);
}
+static int tegra_pmc_init_sub_devs(struct tegra_pmc *pmc)
+{
+ int ret, i;
+
+ if (!pmc->soc->num_sub_devs)
+ return 0;
+
+ pmc->plat_subdevs = devm_kzalloc(pmc->dev, pmc->soc->num_sub_devs *
+ sizeof(**pmc->plat_subdevs),
+ GFP_KERNEL);
+ if (!pmc->plat_subdevs)
+ return -ENOMEM;
+
+ for (i = 0; i < pmc->soc->num_sub_devs; ++i) {
+ pmc->plat_subdevs[i] = platform_device_register_data(pmc->dev,
+ pmc->soc->sub_devs_name[i],
+ 0, NULL, 0);
+ if (IS_ERR(pmc->plat_subdevs[i])) {
+ ret = PTR_ERR(pmc->plat_subdevs[i]);
+ dev_err(pmc->dev,
+ "Failed to register platform device for %s: %d\n",
+ pmc->soc->sub_devs_name[i], ret);
+ goto pdev_cleanups;
+ }
+ }
+
+ return 0;
+
+pdev_cleanups:
+ while (--i >= 0) {
+ platform_device_unregister(pmc->plat_subdevs[i]);
+ pmc->plat_subdevs[i] = NULL;
+ }
+
+ return ret;
+}
+
static int tegra_pmc_probe(struct platform_device *pdev)
{
void __iomem *base;
@@ -1426,6 +1468,11 @@ static int tegra_pmc_probe(struct platform_device *pdev)
return err;
}
+ err = tegra_pmc_init_sub_devs(pmc);
+ if (err < 0)
+ dev_warn(pmc->dev, "Failed to register PMC sub devices: %d\n",
+ err);
+
mutex_lock(&pmc->powergates_lock);
iounmap(pmc->base);
pmc->base = base;
@@ -1608,6 +1655,10 @@ static const struct tegra_io_pad_soc tegra124_io_pads[] = {
{ .id = TEGRA_IO_PAD_USB_BIAS, .dpd = 12, .voltage = UINT_MAX },
};
+static const char *tegra124_sub_devs_name[] = {
+ "pinctrl-t124-io-pad",
+};
+
static const struct tegra_pmc_soc tegra124_pmc_soc = {
.num_powergates = ARRAY_SIZE(tegra124_powergates),
.powergates = tegra124_powergates,
@@ -1617,6 +1668,8 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
.has_gpu_clamps = true,
.num_io_pads = ARRAY_SIZE(tegra124_io_pads),
.io_pads = tegra124_io_pads,
+ .sub_devs_name = tegra124_sub_devs_name,
+ .num_sub_devs = ARRAY_SIZE(tegra124_sub_devs_name),
};
static const char * const tegra210_powergates[] = {
@@ -1694,6 +1747,10 @@ static const struct tegra_io_pad_soc tegra210_io_pads[] = {
{ .id = TEGRA_IO_PAD_USB_BIAS, .dpd = 12, .voltage = UINT_MAX },
};
+static const char *tegra210_sub_devs_name[] = {
+ "pinctrl-t210-io-pad",
+};
+
static const struct tegra_pmc_soc tegra210_pmc_soc = {
.num_powergates = ARRAY_SIZE(tegra210_powergates),
.powergates = tegra210_powergates,
@@ -1703,6 +1760,8 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
.has_gpu_clamps = true,
.num_io_pads = ARRAY_SIZE(tegra210_io_pads),
.io_pads = tegra210_io_pads,
+ .sub_devs_name = tegra210_sub_devs_name,
+ .num_sub_devs = ARRAY_SIZE(tegra210_sub_devs_name),
};
static const struct of_device_id tegra_pmc_match[] = {
--
2.1.4
^ permalink raw reply related
* [PATCH V2 2/4] soc/tegra: pmc: Add interface to get IO pad power status
From: Laxman Dewangan @ 2016-11-09 13:09 UTC (permalink / raw)
To: thierry.reding-Re5JQEeQqe8AvxtiuMwx3w,
swarren-3lzwWm7+Weoh9ZMKESR00Q
Cc: gnurou-Re5JQEeQqe8AvxtiuMwx3w, jonathanh-DDmLM1+adcrQT0dZR+AlfA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Laxman Dewangan
In-Reply-To: <1478696962-11831-1-git-send-email-ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
Add API to get the IO pad power status of the Tegra IO pads.
This will help client driver to get the current power status
of IO pads for handling IO pad power.
Signed-off-by: Laxman Dewangan <ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
Changes from V1:
None
---
drivers/soc/tegra/pmc.c | 22 ++++++++++++++++++++++
include/soc/tegra/pmc.h | 6 ++++++
2 files changed, 28 insertions(+)
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index bb3715f..44546bd 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1063,6 +1063,28 @@ int tegra_io_pad_power_disable(enum tegra_io_pad id)
}
EXPORT_SYMBOL(tegra_io_pad_power_disable);
+int tegra_io_pad_power_get_status(enum tegra_io_pad id)
+{
+ const struct tegra_io_pad_soc *pad;
+ unsigned long status;
+ u32 value;
+ int bit;
+
+ pad = tegra_io_pad_find(pmc, id);
+ if (!pad)
+ return -ENOENT;
+
+ if (pad->dpd == UINT_MAX)
+ return -ENOTSUPP;
+
+ status = (pad->dpd < 32) ? IO_DPD_STATUS : IO_DPD2_STATUS;
+ bit = pad->dpd % 32;
+ value = tegra_pmc_readl(status);
+
+ return !!(value & BIT(bit));
+}
+EXPORT_SYMBOL(tegra_io_pad_power_get_status);
+
int tegra_io_pad_set_voltage(enum tegra_io_pad id,
enum tegra_io_pad_voltage voltage)
{
diff --git a/include/soc/tegra/pmc.h b/include/soc/tegra/pmc.h
index 9c314a6..18cf172 100644
--- a/include/soc/tegra/pmc.h
+++ b/include/soc/tegra/pmc.h
@@ -152,6 +152,7 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
int tegra_io_pad_power_enable(enum tegra_io_pad id);
int tegra_io_pad_power_disable(enum tegra_io_pad id);
+int tegra_io_pad_power_get_status(enum tegra_io_pad id);
int tegra_io_pad_set_voltage(enum tegra_io_pad id,
enum tegra_io_pad_voltage voltage);
int tegra_io_pad_get_voltage(enum tegra_io_pad id);
@@ -193,6 +194,11 @@ static inline int tegra_io_pad_power_disable(enum tegra_io_pad id)
return -ENOSYS;
}
+static inline int tegra_io_pad_power_get_status(enum tegra_io_pad id)
+{
+ return -ENOSYS;
+}
+
static inline int tegra_io_pad_set_voltage(enum tegra_io_pad id,
enum tegra_io_pad_voltage voltage)
{
--
2.1.4
^ permalink raw reply related
* [PATCH V2 1/4] soc/tegra: pmc: Remove legacy Tegra I/O rail API
From: Laxman Dewangan @ 2016-11-09 13:09 UTC (permalink / raw)
To: thierry.reding-Re5JQEeQqe8AvxtiuMwx3w,
swarren-3lzwWm7+Weoh9ZMKESR00Q
Cc: gnurou-Re5JQEeQqe8AvxtiuMwx3w, jonathanh-DDmLM1+adcrQT0dZR+AlfA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Laxman Dewangan
In-Reply-To: <1478696962-11831-1-git-send-email-ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
Remove tegra_io_rail_power_on() and tegra_io_rail_power_off()
from header as client has been moved to new APIs.
Signed-off-by: Laxman Dewangan <ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
Changes from V1:
None
---
include/soc/tegra/pmc.h | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/include/soc/tegra/pmc.h b/include/soc/tegra/pmc.h
index 52780a77..9c314a6 100644
--- a/include/soc/tegra/pmc.h
+++ b/include/soc/tegra/pmc.h
@@ -203,16 +203,6 @@ static inline int tegra_io_pad_get_voltage(enum tegra_io_pad id)
{
return -ENOSYS;
}
-
-static inline int tegra_io_rail_power_on(unsigned int id)
-{
- return -ENOSYS;
-}
-
-static inline int tegra_io_rail_power_off(unsigned int id)
-{
- return -ENOSYS;
-}
#endif /* CONFIG_ARCH_TEGRA */
#endif /* __SOC_TEGRA_PMC_H__ */
--
2.1.4
^ permalink raw reply related
* [PATCH V2 0/4] soc/tegra: pmc: Add support for IO pad configuration and sub-driver
From: Laxman Dewangan @ 2016-11-09 13:09 UTC (permalink / raw)
To: thierry.reding-Re5JQEeQqe8AvxtiuMwx3w,
swarren-3lzwWm7+Weoh9ZMKESR00Q
Cc: gnurou-Re5JQEeQqe8AvxtiuMwx3w, jonathanh-DDmLM1+adcrQT0dZR+AlfA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Laxman Dewangan
Tegra SoC support the configutaion of IO pads to multi-level voltage
and low power state. The conifguration is done via pictrl framework
and the io pad driver in pinctrl frameowrk uses the APIs from pmc to
access PMC registers.
his series add the API to get the IO pad power status and register
the pmc child devices like IO pad drvier.
The patches were send earlier part of different series but applied
partially in the Thierry's t186 branch
https://github.com/thierryreding/linux/tree/tegra186.
Resending the patches as the new start to avoid any confusion.
This need to be applied in
https://github.com/thierryreding/linux/tree/tegra186
---
Changes from V1:
- make the IO pad votlage configurations to the atomic context as 4th patch of
series.
Laxman Dewangan (4):
soc/tegra: pmc: Remove legacy Tegra I/O rail API
soc/tegra: pmc: Add interface to get IO pad power status
soc/tegra: pmc: Register PMC child devices as platform device
soc/tegra: pmc: Make configuration of IO pads in atomic context
drivers/soc/tegra/pmc.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++--
include/soc/tegra/pmc.h | 14 +++-----
2 files changed, 91 insertions(+), 11 deletions(-)
--
2.1.4
^ permalink raw reply
* Re: [PATCH] kernel.bbclass: Allow ${S} to be overridden
From: Bruce Ashfield @ 2016-11-09 13:09 UTC (permalink / raw)
To: Burton, Ross; +Cc: OpenEmbedded Core
In-Reply-To: <CAJTo0LZxGYzpjUetPspX6mKktoL_XnDqfncyHFWN5Kzfij8-UQ@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2577 bytes --]
On Wed, Nov 9, 2016 at 5:04 AM, Burton, Ross <ross.burton@intel.com> wrote:
>
> On 9 November 2016 at 02:23, Bruce Ashfield <bruce.ashfield@gmail.com>
> wrote:
>
>> I can ack this patch, since no defaults change .. there's no risk to
>> existing users.
>>
>
> Saying that of course doomed the patch:
>
interesting.
Paul: obviously you were building with this in place, and my local test did
work here
as well .. so any idea to the difference ?
Let me know if you want any help looking into it.
Cheers,
Bruce
>
> ERROR: hello-mod-0.1-r0 do_make_scripts: Function failed: do_make_scripts
> (log file is located at /home/pokybuild/yocto-autobuilder/yocto-worker/
> nightly-qa-skeleton/build/build/tmp/work/qemux86_64-
> poky-linux/hello-mod/0.1-r0/temp/log.do_make_scripts.14071)
> ERROR: Logfile of failure stored in: /home/pokybuild/yocto-
> autobuilder/yocto-worker/nightly-qa-skeleton/build/
> build/tmp/work/qemux86_64-poky-linux/hello-mod/0.1-r0/
> temp/log.do_make_scripts.14071
> Log data follows:
> | DEBUG: Executing shell function do_make_scripts
> | make: Entering directory '/home/pokybuild/yocto-
> autobuilder/yocto-worker/nightly-qa-skeleton/build/
> build/tmp/work-shared/qemux86-64/kernel-source'
> | make: *** No rule to make target 'scripts'. Stop.
> | make: Leaving directory '/home/pokybuild/yocto-autobuilder/yocto-worker/
> nightly-qa-skeleton/build/build/tmp/work-shared/qemux86-64/kernel-source'
> | WARNING: /home/pokybuild/yocto-autobuilder/yocto-worker/
> nightly-qa-skeleton/build/build/tmp/work/qemux86_64-
> poky-linux/hello-mod/0.1-r0/temp/run.do_make_scripts.14071:1 exit 2 from
> 'make CC="x86_64-poky-linux-gcc -fuse-ld=bfd" LD="x86_64-poky-linux-ld.bfd
> " AR="x86_64-poky-linux-ar " -C /home/pokybuild/yocto-
> autobuilder/yocto-worker/nightly-qa-skeleton/build/
> build/tmp/work-shared/qemux86-64/kernel-source O=/home/pokybuild/yocto-
> autobuilder/yocto-worker/nightly-qa-skeleton/build/
> build/tmp/work-shared/qemux86-64/kernel-build-artifacts scripts'
> | ERROR: Function failed: do_make_scripts (log file is located at
> /home/pokybuild/yocto-autobuilder/yocto-worker/nightly-qa-skeleton/build/
> build/tmp/work/qemux86_64-poky-linux/hello-mod/0.1-r0/
> temp/log.do_make_scripts.14071)
> NOTE: recipe hello-mod-0.1-r0: task do_make_scripts: Failed
>
> The autobuilder builds hello-mod from meta-skeleton, which inherits module
> and sets S=${WORKDIR}.
>
> Ross
>
--
"Thou shalt not follow the NULL pointer, for chaos and madness await thee
at its end"
[-- Attachment #2: Type: text/html, Size: 3891 bytes --]
^ permalink raw reply
* [PATCH] app/test: fix crash of lpm test
From: Olivier Matz @ 2016-11-09 13:08 UTC (permalink / raw)
To: dev, wei.dai; +Cc: bruce.richardson
The test recently added accesses to lpm->tbl8[ip >> 8] with is much
larger than the size of the table, causing a crash of the test
application.
Fix this typo by replacing tbl8 by tbl24.
Fixes: 231fa88ed522 ("app/test: verify LPM tbl8 recycle")
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
Hi Wei,
I don't know lpm very well and I did not spend much time to understand
the test case. I guess that's the proper fix, but please check carefully
that I'm not doing something wrong :)
Thanks,
Olivier
app/test/test_lpm.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/app/test/test_lpm.c b/app/test/test_lpm.c
index 80e0efc..41ae80f 100644
--- a/app/test/test_lpm.c
+++ b/app/test/test_lpm.c
@@ -1256,7 +1256,7 @@ test18(void)
rte_lpm_add(lpm, ip, depth, next_hop);
TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
- tbl8_group_index = lpm->tbl8[ip>>8].group_idx;
+ tbl8_group_index = lpm->tbl24[ip>>8].group_idx;
depth = 23;
next_hop = 2;
@@ -1272,7 +1272,7 @@ test18(void)
rte_lpm_add(lpm, ip, depth, next_hop);
TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
- TEST_LPM_ASSERT(tbl8_group_index == lpm->tbl8[ip>>8].group_idx);
+ TEST_LPM_ASSERT(tbl8_group_index == lpm->tbl24[ip>>8].group_idx);
depth = 24;
next_hop = 4;
@@ -1288,7 +1288,7 @@ test18(void)
rte_lpm_add(lpm, ip, depth, next_hop);
TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
- TEST_LPM_ASSERT(tbl8_group_index == lpm->tbl8[ip>>8].group_idx);
+ TEST_LPM_ASSERT(tbl8_group_index == lpm->tbl24[ip>>8].group_idx);
rte_lpm_free(lpm);
#undef group_idx
--
2.8.1
^ permalink raw reply related
* Re: [Qemu-devel] [kvm-unit-tests PATCH v4 09/11] arm/arm64: add initial gicv3 support
From: Andrew Jones @ 2016-11-09 13:08 UTC (permalink / raw)
To: Andre Przywara
Cc: kvm, kvmarm, qemu-devel, qemu-arm, peter.maydell, marc.zyngier,
eric.auger, pbonzini, alex.bennee, christoffer.dall
In-Reply-To: <c58f7b92-cd37-ebfd-59b8-71c87032b197@arm.com>
On Wed, Nov 09, 2016 at 12:35:48PM +0000, Andre Przywara wrote:
[...]
> > diff --git a/lib/arm/asm/gic-v3.h b/lib/arm/asm/gic-v3.h
> > new file mode 100644
> > index 000000000000..03321f8c860f
> > --- /dev/null
> > +++ b/lib/arm/asm/gic-v3.h
> > @@ -0,0 +1,92 @@
> > +/*
> > + * All GIC* defines are lifted from include/linux/irqchip/arm-gic-v3.h
> > + *
> > + * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> > + *
> > + * This work is licensed under the terms of the GNU LGPL, version 2.
> > + */
> > +#ifndef _ASMARM_GIC_V3_H_
> > +#define _ASMARM_GIC_V3_H_
> > +
> > +#ifndef _ASMARM_GIC_H_
> > +#error Do not directly include <asm/gic-v3.h>. Include <asm/gic.h>
> > +#endif
> > +
> > +#define GICD_CTLR 0x0000
> > +#define GICD_TYPER 0x0004
>
> So if we share the distributor register definition with GICv2, these
> shouldn't be here, but in gic.h.
> But this is the right naming scheme we should use (instead of GIC_DIST_xxx).
>
> Now this gets interesting with your wish to both share the definitions
> for the GICv2 and GICv3 distributors, but also stick to the names the
> kernel uses (because they differ between the two) ;-)
> So now you loose the greppability for either GIC_DIST_CTR or GICD_TYPER,
> for instance.
Well, we just have the same offset with two names (giving us two
symbols to grep). I put them here, vs. asm/gic.h, because the kernel
only uses theses symbols for gicv3. Now, nothing stops a unit test
from using them with gicv2 tests, though, because unit tests include
gic.h, which includes both gic-v2.h and gic-v3.h, and thus it gets
both. I know, it's sounding messy... Shouldn't we post some churn to
the kernel? :-)
Note, I tried to only add defines to asm/gic.h that are actually
shared in the kernel between v2 and v3, e.g. GIC_DIST_ENABLE_SET.
Actually, GIC_DIST_CTRL and GIC_DIST_CTR may be the only exceptions
we have so far.
>
> > +#define GICD_IGROUPR 0x0080
> > +
> > +#define GICD_CTLR_RWP (1U << 31)
> > +#define GICD_CTLR_ARE_NS (1U << 4)
> > +#define GICD_CTLR_ENABLE_G1A (1U << 1)
> > +#define GICD_CTLR_ENABLE_G1 (1U << 0)
> > +
> > +#define GICR_TYPER 0x0008
> > +#define GICR_IGROUPR0 GICD_IGROUPR
> > +#define GICR_TYPER_LAST (1U << 4)
> > +
> > +
> > +#include <asm/arch_gicv3.h>
> > +
> > +#ifndef __ASSEMBLY__
> > +#include <asm/setup.h>
> > +#include <asm/smp.h>
> > +#include <asm/processor.h>
> > +#include <asm/io.h>
> > +
> > +struct gicv3_data {
> > + void *dist_base;
> > + void *redist_base[NR_CPUS];
> > + unsigned int irq_nr;
> > +};
> > +extern struct gicv3_data gicv3_data;
> > +
> > +#define gicv3_dist_base() (gicv3_data.dist_base)
> > +#define gicv3_redist_base() (gicv3_data.redist_base[smp_processor_id()])
> > +#define gicv3_sgi_base() (gicv3_data.redist_base[smp_processor_id()] + SZ_64K)
> > +
> > +extern int gicv3_init(void);
> > +extern void gicv3_enable_defaults(void);
> > +
> > +static inline void gicv3_do_wait_for_rwp(void *base)
> > +{
> > + int count = 100000; /* 1s */
> > +
> > + while (readl(base + GICD_CTLR) & GICD_CTLR_RWP) {
> > + if (!--count) {
> > + printf("GICv3: RWP timeout!\n");
> > + abort();
> > + }
> > + cpu_relax();
> > + udelay(10);
> > + };
> > +}
> > +
> > +static inline void gicv3_dist_wait_for_rwp(void)
> > +{
> > + gicv3_do_wait_for_rwp(gicv3_dist_base());
> > +}
> > +
> > +static inline void gicv3_redist_wait_for_rwp(void)
> > +{
> > + gicv3_do_wait_for_rwp(gicv3_redist_base());
> > +}
> > +
> > +static inline u32 mpidr_compress(u64 mpidr)
> > +{
> > + u64 compressed = mpidr & MPIDR_HWID_BITMASK;
> > +
> > + compressed = (((compressed >> 32) & 0xff) << 24) | compressed;
> > + return compressed;
> > +}
> > +
> > +static inline u64 mpidr_uncompress(u32 compressed)
> > +{
> > + u64 mpidr = ((u64)compressed >> 24) << 32;
> > +
> > + mpidr |= compressed & MPIDR_HWID_BITMASK;
> > + return mpidr;
> > +}
> > +
> > +#endif /* !__ASSEMBLY__ */
> > +#endif /* _ASMARM_GIC_V3_H_ */
> > diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h
> > index 328e078a9ae1..4897bc592cdd 100644
> > --- a/lib/arm/asm/gic.h
> > +++ b/lib/arm/asm/gic.h
> > @@ -7,6 +7,7 @@
> > #define _ASMARM_GIC_H_
> >
> > #include <asm/gic-v2.h>
> > +#include <asm/gic-v3.h>
> >
> > #define GIC_CPU_CTRL 0x00
> > #define GIC_CPU_PRIMASK 0x04
> > diff --git a/lib/arm/gic.c b/lib/arm/gic.c
> > index 91d78c9a0cc2..af58a11ea13e 100644
> > --- a/lib/arm/gic.c
> > +++ b/lib/arm/gic.c
> > @@ -8,9 +8,11 @@
> > #include <asm/io.h>
> >
> > struct gicv2_data gicv2_data;
> > +struct gicv3_data gicv3_data;
> >
> > /*
> > * Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
> > + * Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt
> > */
> > static bool
> > gic_get_dt_bases(const char *compatible, void **base1, void **base2)
> > @@ -48,10 +50,18 @@ int gicv2_init(void)
> > &gicv2_data.dist_base, &gicv2_data.cpu_base);
> > }
> >
> > +int gicv3_init(void)
> > +{
> > + return gic_get_dt_bases("arm,gic-v3", &gicv3_data.dist_base,
> > + &gicv3_data.redist_base[0]);
> > +}
> > +
> > int gic_init(void)
> > {
> > if (gicv2_init())
> > return 2;
> > + else if (gicv3_init())
> > + return 3;
> > return 0;
> > }
> >
> > @@ -73,3 +83,49 @@ void gicv2_enable_defaults(void)
> > writel(GICC_INT_PRI_THRESHOLD, cpu_base + GIC_CPU_PRIMASK);
> > writel(GICC_ENABLE, cpu_base + GIC_CPU_CTRL);
> > }
> > +
> > +void gicv3_set_redist_base(void)
> > +{
> > + u32 aff = mpidr_compress(get_mpidr());
> > + void *ptr = gicv3_data.redist_base[0];
> > + u64 typer;
> > +
> > + do {
> > + typer = gicv3_read_typer(ptr + GICR_TYPER);
> > + if ((typer >> 32) == aff) {
> > + gicv3_redist_base() = ptr;
> > + return;
> > + }
> > + ptr += SZ_64K * 2; /* skip RD_base and SGI_base */
> > + } while (!(typer & GICR_TYPER_LAST));
> > + assert(0);
> > +}
> > +
> > +void gicv3_enable_defaults(void)
> > +{
> > + void *dist = gicv3_dist_base();
> > + void *sgi_base;
> > + unsigned int i;
> > +
> > + gicv3_data.irq_nr = GICD_TYPER_IRQS(readl(dist + GICD_TYPER));
> > + if (gicv3_data.irq_nr > 1020)
> > + gicv3_data.irq_nr = 1020;
> > +
> > + writel(GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1,
> > + dist + GICD_CTLR);
> > + gicv3_dist_wait_for_rwp();
> > +
> > + if (!gicv3_redist_base())
> > + gicv3_set_redist_base();
> > + sgi_base = gicv3_sgi_base();
> > +
> > + writel(~0, sgi_base + GICR_IGROUPR0);
>
> This is mixing redist setup with distributor setup. Is it that what you
> meant with:
> " - simplify enable by not caring if we reinit the distributor [drew]"?
Yes, but, TBH, I wasn't sure I could get away with it. I tested and it
worked, and I figured you'd yell at me if I was wrong :-)
>
> Also if you set the group for the SGIs, you should set it for SPIs as
> well (like the kernel does). This was done in v3 of the series.
OK, I was also simplifying by removing everything and then adding stuff
back until it worked :-) I can certainly add this back for completeness
though.
>
> What about you finish the per-CPU setup first, then bail out with:
>
> if (smp_processor_id() != 0)
> return;
>
> and then do the distributor setup (only on the first core).
Sure, if it's necessary. I actually like not having to worry about
a particular core or a particular order/number of times this enable
gets called. Does it hurt to just do it each time?
Thanks,
drew
^ permalink raw reply
* Re: [PATCH v3 4/4] drm/i915: Implement Link Rate fallback on Link training failure
From: Jani Nikula @ 2016-11-09 13:07 UTC (permalink / raw)
To: Manasi Navare, intel-gfx; +Cc: Daniel Vetter
In-Reply-To: <20161107192439.GA24899@intel.com>
On Mon, 07 Nov 2016, Manasi Navare <manasi.d.navare@intel.com> wrote:
> Jani, could you please take a look at this patch?
> I have addressed your comments on the previous revision.
> The common_rates array can be moved into Intel dp
> structure in a follow up patch since that would require changes
> in a lot of places other than the link rate fallback implementation.
I think this is looking good. I think you need to put this together in a
series that doesn't add something first, and then remove it, i.e. build
a coherent story from the start. It's not that many patches. Then you
need to post all patches on both intel-gfx and dri-devel, preferrably in
a fresh thread, not replying to previous versions. The thread is too
confusing now with so many versions.
Then we need to get r-b and acks for the drm changes. Daniel, can you
help with the last part?
BR,
Jani.
--
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply
* [PATCH V2 2/2] pinctrl: tegra: Add driver to configure voltage and power of io pads
From: Laxman Dewangan @ 2016-11-09 13:06 UTC (permalink / raw)
To: linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
swarren-3lzwWm7+Weoh9ZMKESR00Q,
thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
Cc: gnurou-Re5JQEeQqe8AvxtiuMwx3w,
yamada.masahiro-uWyLwvC0a2jby3iVrkZq2A,
jonathanh-DDmLM1+adcrQT0dZR+AlfA,
linux-gpio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Laxman Dewangan
In-Reply-To: <1478696782-11657-1-git-send-email-ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
NVIDIA Tegra124 and later SoCs support the multi-voltage level and
low power state of some of its IO pads. The IO pads can work in
the voltage of the 1.8V and 3.3V of IO voltage from IO power rail
sources. When IO interfaces are not used then IO pads can be
configure in low power state to reduce the power consumption from
that IO pads.
On Tegra124, the voltage level of IO power rail source is auto
detected by hardware(SoC) and hence it is only require to configure
in low power mode if IO pads are not used.
On T210 onwards, the auto-detection of voltage level from IO power
rail is removed from SoC and hence SW need to configure the PMC
register explicitly to set proper voltage in IO pads based on
IO rail power source voltage.
This driver adds the IO pad driver to configure the power state and
IO pad voltage based on the usage and power tree via pincontrol
framework. The configuration can be static and dynamic.
Signed-off-by: Laxman Dewangan <ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
Changes from V1:
- Dropped the custom properties to set pad voltage and use regulator.
- Added support for regulator to get vottage in boot and configure IO
pad voltage.
- Add support for callback to handle regulator notification and configure
IO pad voltage based on voltage change.
---
drivers/pinctrl/tegra/Kconfig | 12 +
drivers/pinctrl/tegra/Makefile | 1 +
drivers/pinctrl/tegra/pinctrl-tegra-io-pad.c | 488 +++++++++++++++++++++++++++
3 files changed, 501 insertions(+)
create mode 100644 drivers/pinctrl/tegra/pinctrl-tegra-io-pad.c
diff --git a/drivers/pinctrl/tegra/Kconfig b/drivers/pinctrl/tegra/Kconfig
index 24e20cc..6004e5c 100644
--- a/drivers/pinctrl/tegra/Kconfig
+++ b/drivers/pinctrl/tegra/Kconfig
@@ -23,6 +23,18 @@ config PINCTRL_TEGRA210
bool
select PINCTRL_TEGRA
+config PINCTRL_TEGRA_IO_PAD
+ bool "Tegra IO pad Control Driver"
+ depends on ARCH_TEGRA && REGULATOR
+ select PINCONF
+ select PINMUX
+ help
+ NVIDIA Tegra124/210 SoC has IO pads which supports multi-voltage
+ level of interfacing and deep power down mode of IO pads. The
+ voltage of IO pads are SW configurable based on IO rail of that
+ pads on T210. This driver provides the interface to change IO pad
+ voltage and power state via pincontrol interface.
+
config PINCTRL_TEGRA_XUSB
def_bool y if ARCH_TEGRA
select GENERIC_PHY
diff --git a/drivers/pinctrl/tegra/Makefile b/drivers/pinctrl/tegra/Makefile
index d9ea2be..3ebaaa2 100644
--- a/drivers/pinctrl/tegra/Makefile
+++ b/drivers/pinctrl/tegra/Makefile
@@ -4,4 +4,5 @@ obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o
obj-$(CONFIG_PINCTRL_TEGRA114) += pinctrl-tegra114.o
obj-$(CONFIG_PINCTRL_TEGRA124) += pinctrl-tegra124.o
obj-$(CONFIG_PINCTRL_TEGRA210) += pinctrl-tegra210.o
+obj-$(CONFIG_PINCTRL_TEGRA_IO_PAD) += pinctrl-tegra-io-pad.o
obj-$(CONFIG_PINCTRL_TEGRA_XUSB) += pinctrl-tegra-xusb.o
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra-io-pad.c b/drivers/pinctrl/tegra/pinctrl-tegra-io-pad.c
new file mode 100644
index 0000000..f5cf0d0
--- /dev/null
+++ b/drivers/pinctrl/tegra/pinctrl-tegra-io-pad.c
@@ -0,0 +1,488 @@
+/*
+ * pinctrl-tegra-io-pad: IO PAD driver for configuration of IO rail and deep
+ * Power Down mode via pinctrl framework.
+ *
+ * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved.
+ *
+ * Author: Laxman Dewangan <ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
+ *
+ * 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.
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <soc/tegra/pmc.h>
+
+#include "../core.h"
+#include "../pinconf.h"
+#include "../pinctrl-utils.h"
+
+/**
+ * Macro for 1.8V, keep 200mV as tolerance for deciding that
+ * IO pads should be set for 3.3V (high voltage) or 1.8V.
+ */
+#define TEGRA_IO_PAD_1800000UV_UPPER_LIMIT 2000000
+
+struct tegra_io_pads_cfg_info {
+ const char *name;
+ const unsigned int pins[1];
+ const char *vsupply;
+ enum tegra_io_pad pad_id;
+ bool support_low_power_state;
+};
+
+struct tegra_io_pad_soc_data {
+ const struct tegra_io_pads_cfg_info *pads_cfg;
+ int num_pads_cfg;
+ const struct pinctrl_pin_desc *pins_desc;
+ int num_pins_desc;
+};
+
+struct tegra_io_pads_regulator_info {
+ struct device *dev;
+ const struct tegra_io_pads_cfg_info *pads_cfg;
+ struct regulator *regulator;
+ struct notifier_block regulator_nb;
+};
+
+struct tegra_io_pads_info {
+ struct device *dev;
+ struct pinctrl_dev *pctl;
+ struct tegra_io_pads_regulator_info *rinfo;
+ const struct tegra_io_pad_soc_data *soc_data;
+};
+
+static int tegra_iop_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ struct tegra_io_pads_info *tiopi = pinctrl_dev_get_drvdata(pctldev);
+
+ return tiopi->soc_data->num_pads_cfg;
+}
+
+static const char *tegra_iop_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned int group)
+{
+ struct tegra_io_pads_info *tiopi = pinctrl_dev_get_drvdata(pctldev);
+
+ return tiopi->soc_data->pads_cfg[group].name;
+}
+
+static int tegra_iop_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned int group,
+ const unsigned int **pins,
+ unsigned int *num_pins)
+{
+ struct tegra_io_pads_info *tiopi = pinctrl_dev_get_drvdata(pctldev);
+
+ *pins = tiopi->soc_data->pads_cfg[group].pins;
+ *num_pins = 1;
+
+ return 0;
+}
+
+static const struct pinctrl_ops tegra_iop_pinctrl_ops = {
+ .get_groups_count = tegra_iop_pinctrl_get_groups_count,
+ .get_group_name = tegra_iop_pinctrl_get_group_name,
+ .get_group_pins = tegra_iop_pinctrl_get_group_pins,
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_free_map,
+};
+
+static int tegra_io_pad_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned long *config)
+{
+ struct tegra_io_pads_info *tiopi = pinctrl_dev_get_drvdata(pctldev);
+ int param = pinconf_to_config_param(*config);
+ const struct tegra_io_pads_cfg_info *pads_cfg =
+ &tiopi->soc_data->pads_cfg[pin];
+ enum tegra_io_pad pad_id = pads_cfg->pad_id;
+ int arg = 0;
+ int ret;
+
+ switch (param) {
+ case PIN_CONFIG_LOW_POWER_MODE:
+ ret = tegra_io_pad_power_get_status(pad_id);
+ if (ret < 0)
+ return ret;
+ arg = !ret;
+ break;
+
+ default:
+ dev_err(tiopi->dev, "The parameter %d not supported\n", param);
+ return -EINVAL;
+ }
+
+ *config = pinconf_to_config_packed(param, (u16)arg);
+ return 0;
+}
+
+static int tegra_io_pad_pinconf_set(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned long *configs,
+ unsigned int num_configs)
+{
+ struct tegra_io_pads_info *tiopi = pinctrl_dev_get_drvdata(pctldev);
+ const struct tegra_io_pads_cfg_info *pads_cfg =
+ &tiopi->soc_data->pads_cfg[pin];
+ int pad_id = pads_cfg->pad_id;
+ u16 param_val;
+ int param;
+ int ret;
+ int i;
+
+ for (i = 0; i < num_configs; i++) {
+ param = pinconf_to_config_param(configs[i]);
+ param_val = pinconf_to_config_argument(configs[i]);
+
+ switch (param) {
+ case PIN_CONFIG_LOW_POWER_MODE:
+ if (param_val)
+ ret = tegra_io_pad_power_disable(pad_id);
+ else
+ ret = tegra_io_pad_power_enable(pad_id);
+ if (ret < 0) {
+ dev_err(tiopi->dev,
+ "Failed to set DPD %d of pin %u: %d\n",
+ param_val, pin, ret);
+ return ret;
+ }
+ break;
+
+ default:
+ dev_err(tiopi->dev, "The parameter %d not supported\n",
+ param);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static const struct pinconf_ops tegra_io_pad_pinconf_ops = {
+ .pin_config_get = tegra_io_pad_pinconf_get,
+ .pin_config_set = tegra_io_pad_pinconf_set,
+};
+
+static struct pinctrl_desc tegra_iop_pinctrl_desc = {
+ .name = "pinctrl-tegra-io-pads",
+ .pctlops = &tegra_iop_pinctrl_ops,
+ .confops = &tegra_io_pad_pinconf_ops,
+};
+
+static int tegra_io_pads_rail_change_notify_cb(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct tegra_io_pads_regulator_info *rinfo;
+ struct pre_voltage_change_data *vdata;
+ unsigned long int io_volt_uv, old_uv;
+ enum tegra_io_pad_voltage io_volt;
+ int ret;
+
+ rinfo = container_of(nb, struct tegra_io_pads_regulator_info,
+ regulator_nb);
+
+ switch (event) {
+ case REGULATOR_EVENT_PRE_VOLTAGE_CHANGE:
+ vdata = data;
+ if ((vdata->old_uV > TEGRA_IO_PAD_1800000UV_UPPER_LIMIT) &&
+ (vdata->min_uV <= TEGRA_IO_PAD_1800000UV_UPPER_LIMIT))
+ break;
+
+ ret = tegra_io_pad_set_voltage(rinfo->pads_cfg->pad_id,
+ TEGRA_IO_PAD_3300000UV);
+ if (ret < 0) {
+ dev_err(rinfo->dev,
+ "Failed to set voltage %lu of pad %s: %d\n",
+ vdata->min_uV, rinfo->pads_cfg->name, ret);
+ return ret;
+ }
+ break;
+
+ case REGULATOR_EVENT_VOLTAGE_CHANGE:
+ io_volt_uv = (unsigned long)data;
+ ret = tegra_io_pad_get_voltage(rinfo->pads_cfg->pad_id);
+ if (ret < 0) {
+ dev_err(rinfo->dev, "Failed to get IO pad voltage: %d\n",
+ ret);
+ return ret;
+ }
+ old_uv = (ret == TEGRA_IO_PAD_1800000UV) ? 1800000 : 3300000;
+ if (((io_volt_uv <= TEGRA_IO_PAD_1800000UV_UPPER_LIMIT) &&
+ (old_uv <= TEGRA_IO_PAD_1800000UV_UPPER_LIMIT)) ||
+ ((io_volt_uv > TEGRA_IO_PAD_1800000UV_UPPER_LIMIT) &&
+ (old_uv > TEGRA_IO_PAD_1800000UV_UPPER_LIMIT)))
+ break;
+
+ ret = tegra_io_pad_set_voltage(rinfo->pads_cfg->pad_id,
+ TEGRA_IO_PAD_1800000UV);
+ if (ret < 0) {
+ dev_err(rinfo->dev,
+ "Failed to set voltage %lu of pad %s: %d\n",
+ vdata->min_uV, rinfo->pads_cfg->name, ret);
+ return ret;
+ }
+ break;
+
+ case REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE:
+ io_volt_uv = (unsigned long)data;
+ io_volt = (io_volt_uv <= TEGRA_IO_PAD_1800000UV_UPPER_LIMIT) ?
+ TEGRA_IO_PAD_1800000UV : TEGRA_IO_PAD_3300000UV;
+ ret = tegra_io_pad_set_voltage(rinfo->pads_cfg->pad_id,
+ io_volt);
+ if (ret < 0) {
+ dev_err(rinfo->dev,
+ "Failed to set voltage %lu of pad %s: %d\n",
+ io_volt_uv, rinfo->pads_cfg->name, ret);
+ return ret;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static int tegra_iop_pinctrl_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ const struct platform_device_id *id = platform_get_device_id(pdev);
+ const struct tegra_io_pad_soc_data *soc_data;
+ struct device_node *np_parent = pdev->dev.parent->of_node;
+ struct tegra_io_pads_info *tiopi;
+ int ret, i;
+
+ if (!np_parent) {
+ dev_err(dev, "PMC should be register from DT\n");
+ return -ENODEV;
+ }
+
+ soc_data = (const struct tegra_io_pad_soc_data *)id->driver_data;
+
+ tiopi = devm_kzalloc(dev, sizeof(*tiopi), GFP_KERNEL);
+ if (!tiopi)
+ return -ENOMEM;
+
+ tiopi->rinfo = devm_kzalloc(dev, sizeof(*tiopi->rinfo) *
+ soc_data->num_pads_cfg, GFP_KERNEL);
+ if (!tiopi->rinfo)
+ return -ENOMEM;
+
+ tiopi->dev = &pdev->dev;
+ pdev->dev.of_node = np_parent;
+ tiopi->soc_data = soc_data;
+
+ for (i = 0; i < soc_data->num_pads_cfg; ++i) {
+ struct tegra_io_pads_regulator_info *rinfo = tiopi->rinfo + i;
+ const struct tegra_io_pads_cfg_info *pads_cfg =
+ &soc_data->pads_cfg[i];
+ struct regulator *regulator;
+ int io_volt_uv;
+ enum tegra_io_pad_voltage io_volt;
+
+ if (!pads_cfg->vsupply)
+ continue;
+
+ regulator = devm_regulator_get_optional(dev, pads_cfg->vsupply);
+ if (IS_ERR(regulator)) {
+ ret = PTR_ERR(regulator);
+ if (ret == -EPROBE_DEFER)
+ return ret;
+ continue;
+ }
+
+ io_volt_uv = regulator_get_voltage(regulator);
+ if (io_volt_uv < 0) {
+ dev_err(dev, "Failed to get voltage for rail %s: %d\n",
+ pads_cfg->vsupply, io_volt_uv);
+ return ret;
+ }
+
+ io_volt = (io_volt_uv <= TEGRA_IO_PAD_1800000UV_UPPER_LIMIT) ?
+ TEGRA_IO_PAD_1800000UV : TEGRA_IO_PAD_3300000UV;
+
+ ret = tegra_io_pad_set_voltage(pads_cfg->pad_id, io_volt);
+ if (ret < 0) {
+ dev_err(dev, "Failed to set voltage %d of pad %s: %d\n",
+ io_volt_uv, pads_cfg->name, ret);
+ return ret;
+ }
+ rinfo->dev = tiopi->dev;
+ rinfo->regulator = regulator;
+ rinfo->pads_cfg = pads_cfg;
+
+ rinfo->regulator_nb.notifier_call =
+ tegra_io_pads_rail_change_notify_cb;
+ ret = devm_regulator_register_notifier(regulator,
+ &rinfo->regulator_nb);
+ if (ret < 0) {
+ dev_err(dev, "Failed to register regulator %s notifier: %d\n",
+ pads_cfg->name, ret);
+ return ret;
+ }
+ }
+
+ tegra_iop_pinctrl_desc.pins = tiopi->soc_data->pins_desc;
+ tegra_iop_pinctrl_desc.npins = tiopi->soc_data->num_pins_desc;
+ platform_set_drvdata(pdev, tiopi);
+
+ tiopi->pctl = devm_pinctrl_register(dev, &tegra_iop_pinctrl_desc,
+ tiopi);
+ if (IS_ERR(tiopi->pctl)) {
+ ret = PTR_ERR(tiopi->pctl);
+ dev_err(dev, "Failed to register io-pad pinctrl driver: %d\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+#define TEGRA124_PAD_INFO_TABLE(_entry_) \
+ _entry_(0, "audio", AUDIO, true, NULL), \
+ _entry_(1, "bb", BB, true, NULL), \
+ _entry_(2, "cam", CAM, true, NULL), \
+ _entry_(3, "comp", COMP, true, NULL), \
+ _entry_(4, "csia", CSIA, true, NULL), \
+ _entry_(5, "csib", CSIB, true, NULL), \
+ _entry_(6, "csie", CSIE, true, NULL), \
+ _entry_(7, "dsi", DSI, true, NULL), \
+ _entry_(8, "dsib", DSIB, true, NULL), \
+ _entry_(9, "dsic", DSIC, true, NULL), \
+ _entry_(10, "dsid", DSID, true, NULL), \
+ _entry_(11, "hdmi", HDMI, true, NULL), \
+ _entry_(12, "hsic", HSIC, true, NULL), \
+ _entry_(13, "hv", HV, true, NULL), \
+ _entry_(14, "lvds", LVDS, true, NULL), \
+ _entry_(15, "mipi-bias", MIPI_BIAS, true, NULL), \
+ _entry_(16, "nand", NAND, true, NULL), \
+ _entry_(17, "pex-bias", PEX_BIAS, true, NULL), \
+ _entry_(18, "pex-clk1", PEX_CLK1, true, NULL), \
+ _entry_(19, "pex-clk2", PEX_CLK2, true, NULL), \
+ _entry_(20, "pex-ctrl", PEX_CNTRL, true, NULL), \
+ _entry_(21, "sdmmc1", SDMMC1, true, NULL), \
+ _entry_(22, "sdmmc3", SDMMC3, true, NULL), \
+ _entry_(23, "sdmmc4", SDMMC4, true, NULL), \
+ _entry_(24, "sys-ddc", SYS_DDC, true, NULL), \
+ _entry_(25, "uart", UART, true, NULL), \
+ _entry_(26, "usb0", USB0, true, NULL), \
+ _entry_(27, "usb1", USB1, true, NULL), \
+ _entry_(28, "usb2", USB2, true, NULL), \
+ _entry_(29, "usb-bias", USB_BIAS, true, NULL)
+
+#define TEGRA210_PAD_INFO_TABLE(_entry_) \
+ _entry_(0, "audio", AUDIO, true, "vddio-audio"), \
+ _entry_(1, "audio-hv", AUDIO_HV, true, "vddio-audio-hv"), \
+ _entry_(2, "cam", CAM, true, "vddio-cam"), \
+ _entry_(3, "csia", CSIA, true, NULL), \
+ _entry_(4, "csib", CSIB, true, NULL), \
+ _entry_(5, "csic", CSIC, true, NULL), \
+ _entry_(6, "csid", CSID, true, NULL), \
+ _entry_(7, "csie", CSIE, true, NULL), \
+ _entry_(8, "csif", CSIF, true, NULL), \
+ _entry_(9, "dbg", DBG, true, "vddio-dbg"), \
+ _entry_(10, "debug-nonao", DEBUG_NONAO, true, NULL), \
+ _entry_(11, "dmic", DMIC, true, "vddio-dmic"), \
+ _entry_(12, "dp", DP, true, NULL), \
+ _entry_(13, "dsi", DSI, true, NULL), \
+ _entry_(14, "dsib", DSIB, true, NULL), \
+ _entry_(15, "dsic", DSIC, true, NULL), \
+ _entry_(16, "dsid", DSID, true, NULL), \
+ _entry_(17, "emmc", SDMMC4, true, NULL), \
+ _entry_(18, "emmc2", EMMC2, true, NULL), \
+ _entry_(19, "gpio", GPIO, true, "vddio-gpio"), \
+ _entry_(20, "hdmi", HDMI, true, NULL), \
+ _entry_(21, "hsic", HSIC, true, NULL), \
+ _entry_(22, "lvds", LVDS, true, NULL), \
+ _entry_(23, "mipi-bias", MIPI_BIAS, true, NULL), \
+ _entry_(24, "pex-bias", PEX_BIAS, true, NULL), \
+ _entry_(25, "pex-clk1", PEX_CLK1, true, NULL), \
+ _entry_(26, "pex-clk2", PEX_CLK2, true, NULL), \
+ _entry_(27, "pex-ctrl", PEX_CNTRL, false, "vddio-pex-ctrl"), \
+ _entry_(28, "sdmmc1", SDMMC1, true, "vddio-sdmmc1"), \
+ _entry_(29, "sdmmc3", SDMMC3, true, "vddio-sdmmc3"), \
+ _entry_(30, "spi", SPI, true, "vddio-spi"), \
+ _entry_(31, "spi-hv", SPI_HV, true, "vddio-spi-hv"), \
+ _entry_(32, "uart", UART, true, "vddio-uart"), \
+ _entry_(33, "usb0", USB0, true, NULL), \
+ _entry_(34, "usb1", USB1, true, NULL), \
+ _entry_(35, "usb2", USB2, true, NULL), \
+ _entry_(36, "usb3", USB3, true, NULL), \
+ _entry_(37, "usb-bias", USB_BIAS, true, NULL)
+
+#define TEGRA_IO_PAD_INFO(_id, _name, _pad_id, _lpstate, _vsupply) \
+ { \
+ .name = _name, \
+ .pins = {(_id)}, \
+ .pad_id = TEGRA_IO_PAD_##_pad_id, \
+ .vsupply = (_vsupply), \
+ .support_low_power_state = (_lpstate), \
+ }
+
+static const struct tegra_io_pads_cfg_info tegra124_io_pads_cfg_info[] = {
+ TEGRA124_PAD_INFO_TABLE(TEGRA_IO_PAD_INFO),
+};
+
+static const struct tegra_io_pads_cfg_info tegra210_io_pads_cfg_info[] = {
+ TEGRA210_PAD_INFO_TABLE(TEGRA_IO_PAD_INFO),
+};
+
+#define TEGRA_IO_PAD_DESC(_id, _name, _pad_id, _lpstate, _vsupply) \
+ PINCTRL_PIN(_id, _name)
+
+static const struct pinctrl_pin_desc tegra124_io_pads_pinctrl_desc[] = {
+ TEGRA124_PAD_INFO_TABLE(TEGRA_IO_PAD_DESC),
+};
+
+static const struct pinctrl_pin_desc tegra210_io_pads_pinctrl_desc[] = {
+ TEGRA210_PAD_INFO_TABLE(TEGRA_IO_PAD_DESC),
+};
+
+static const struct tegra_io_pad_soc_data tegra124_io_pad_soc_data = {
+ .pins_desc = tegra124_io_pads_pinctrl_desc,
+ .num_pins_desc = ARRAY_SIZE(tegra124_io_pads_pinctrl_desc),
+ .pads_cfg = tegra124_io_pads_cfg_info,
+ .num_pads_cfg = ARRAY_SIZE(tegra124_io_pads_cfg_info),
+};
+
+static const struct tegra_io_pad_soc_data tegra210_io_pad_soc_data = {
+ .pins_desc = tegra210_io_pads_pinctrl_desc,
+ .num_pins_desc = ARRAY_SIZE(tegra210_io_pads_pinctrl_desc),
+ .pads_cfg = tegra210_io_pads_cfg_info,
+ .num_pads_cfg = ARRAY_SIZE(tegra210_io_pads_cfg_info),
+};
+
+static const struct platform_device_id tegra_io_pads_dev_id[] = {
+ {
+ .name = "pinctrl-t124-io-pad",
+ .driver_data = (kernel_ulong_t)&tegra124_io_pad_soc_data,
+ }, {
+ .name = "pinctrl-t210-io-pad",
+ .driver_data = (kernel_ulong_t)&tegra210_io_pad_soc_data,
+ }, {
+ },
+};
+MODULE_DEVICE_TABLE(platform, tegra_io_pads_dev_id);
+
+static struct platform_driver tegra_iop_pinctrl_driver = {
+ .driver = {
+ .name = "pinctrl-tegra-io-pad",
+ },
+ .probe = tegra_iop_pinctrl_probe,
+ .id_table = tegra_io_pads_dev_id,
+};
+
+module_platform_driver(tegra_iop_pinctrl_driver);
+
+MODULE_DESCRIPTION("NVIDIA TEGRA IO pad Control Driver");
+MODULE_AUTHOR("Laxman Dewangan <ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>");
+MODULE_LICENSE("GPL v2");
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH V2 1/2] pinctrl: tegra: Add DT binding for io pads control
From: Laxman Dewangan @ 2016-11-09 13:06 UTC (permalink / raw)
To: linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
swarren-3lzwWm7+Weoh9ZMKESR00Q,
thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
Cc: gnurou-Re5JQEeQqe8AvxtiuMwx3w,
yamada.masahiro-uWyLwvC0a2jby3iVrkZq2A,
jonathanh-DDmLM1+adcrQT0dZR+AlfA,
linux-gpio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Laxman Dewangan
In-Reply-To: <1478696782-11657-1-git-send-email-ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
NVIDIA Tegra124 and later SoCs support the multi-voltage level and
low power state of some of its IO pads. The IO pads can work in
the voltage of the 1.8V and 3.3V of IO voltage from IO power rail
sources. When IO interfaces are not used then IO pads can be
configure in low power state to reduce the power consumption from
that IO pads.
On Tegra124, the voltage level of IO power rail source is auto
detected by hardware(SoC) and hence it is only require to configure
in low power mode if IO pads are not used.
On T210 onwards, the auto-detection of voltage level from IO power
rail is removed from SoC and hence SW need to configure the PMC
register explicitly to set proper voltage in IO pads based on
IO rail power source voltage.
Add DT binding document for detailing the DT properties for
configuring IO pads voltage levels and its power state.
Signed-off-by: Laxman Dewangan <ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
Changes from V1:
The DT binding document is modified to explain the regulator handle
for different IOs and how can it be passed from the DT.
---
.../bindings/pinctrl/nvidia,tegra-io-pad.txt | 126 +++++++++++++++++++++
1 file changed, 126 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/nvidia,tegra-io-pad.txt
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra-io-pad.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra-io-pad.txt
new file mode 100644
index 0000000..6ca961f
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra-io-pad.txt
@@ -0,0 +1,126 @@
+NVIDIA Tegra PMC IO pad controller
+
+NVIDIA Tegra124 and later SoCs support the multi-voltage level and
+low power state of some of its IO pads. When IO interface are not
+used then IO pads can be configure in low power state to reduce
+the power from that IO pads. The IO pads can work in the voltage
+of the 1.8V and 3.3V of IO voltage from power rail sources.
+
+On Tegra124, the voltage of IO power rail source is auto detected by
+SoC and hence it is only require to configure in low power mode if
+IO pads are not used.
+
+On T210 onwards, the HW based auto-detection for IO voltage is removed
+and hence SW need to configure the PMC register explicitly, to set proper
+voltage in IO pads, based on IO rail power source voltage.
+
+The voltage configurations and low power state of IO pads should be done
+in boot if it is not going to change other wise dynamically based on IO
+rail voltage on that IO pads and usage of IO pads
+
+The DT property of the io pads must be under the node of pmc i.e.
+pmc@7000e400 for Tegra124 onwards.
+
+Please refer to <pinctrl-bindings.txt> in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+Tegra's pin configuration nodes act as a container for an arbitrary number of
+subnodes. Each of these subnodes represents some desired configuration for an
+IO pads, or a list of IO pads. This configuration can include the voltage and
+power enable/disable control
+
+The name of each subnode is not important; all subnodes should be enumerated
+and processed purely based on their content. Each subnode only affects those
+parameters that are explicitly listed. Unspecified is represented as an absent
+property,
+
+See the TRM to determine which properties and values apply to each IO pads.
+
+Required subnode-properties:
+==========================
+- pins : An array of strings. Each string contains the name of an IO pads. Valid
+ values for these names are listed below.
+
+Optional subnode-properties:
+==========================
+Following properties are supported from generic pin configuration explained
+in <dt-bindings/pinctrl/pinctrl-binding.txt>.
+low-power-enable: enable low power mode.
+low-power-disable: disable low power mode.
+
+Valid values for pin for T124 are:
+ audio, bb, cam, comp, csia, csib, csie, dsi, dsib, dsic, dsid, hdmi,
+ hsic, hv, lvds, mipi-bias, nand, pex-bias, pex-clk1, pex-clk2,
+ pex-ctrl, sdmmc1, sdmmc3, sdmmc4, sys-ddc, uart, usb0, usb1, usb2,
+ usb-bias
+
+Valid values for pin for T210 are:
+ audio, audio-hv, cam, csia, csib, csic, csid, csie, csif,
+ dbg, debug-nonao, dmic, dp, dsi, dsib, dsic, dsid, emmc, emmc2,
+ gpio, hdmi, hsic, lvds, mipi-bias, pex-bias, pex-clk1, pex-clk2,
+ pex-ctrl, sdmmc1, sdmmc3, spi, spi-hv, uart, usb-bias, usb0,
+ usb1, usb2, usb3.
+
+To find out the IO rail voltage for setting the voltage of IO pad by SW,
+the regulator supply handle must provided from the DT and it is explained
+in the regulator DT binding document
+ <devicetree/bindings/regulator/regulator.txt>.
+For example, for GPIO rail the supply name is vddio-gpio and regulator
+handle is supplied from DT as
+ vddio-gpio-supply = <®ulator_xyz>;
+
+For T210, following IO pads support the 1.8V/3.3V and the corresponding
+io voltage pin names are as follows:
+ audio -> vddio-audio
+ audio-hv -> vddio-audio-hv
+ cam ->vddio-cam
+ dbg -> vddio-dbg
+ dmic -> vddio-dmic
+ gpio -> vddio-gpio
+ pex-ctrl -> vddio-pex-ctrl
+ sdmmc1 -> vddio-sdmmc1
+ sdmmc3 -> vddio-sdmmc3
+ spi -> vddio-spi
+ spi-hv -> vddio-spi-hv
+ uart -> vddio-uart
+
+Example:
+ i2c@7000d000 {
+ pmic@3c {
+ regulators {
+ vddio_sdmmc1: ldo2 {
+ /* Regulator entries for LDO2 */
+ };
+
+ vdd_cam: ldo3 {
+ /* Regulator entries for LDO3 */
+ };
+ };
+ };
+ };
+
+ pmc@7000e400 {
+ vddio-cam = <&vdd_cam>;
+ vddio-sdmmc1-supply = <&vddio_sdmmc1>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&tegra_io_pad_volt_default>;
+ tegra_io_pad_volt_default: common {
+ audio-hv {
+ pins = "audio-hv";
+ low-power-disable;
+ };
+
+ gpio {
+ pins = "gpio";
+ low-power-disable;
+ };
+
+ audio {
+ pins = "audio", "dmic", "sdmmc3";
+ low-power-enable;
+ };
+ };
+
+ };
--
2.1.4
^ permalink raw reply related
* [PATCH V2 0/2] pinctrl: tegra: Add support for IO pad control
From: Laxman Dewangan @ 2016-11-09 13:06 UTC (permalink / raw)
To: linus.walleij, robh+dt, mark.rutland, swarren, thierry.reding
Cc: gnurou, yamada.masahiro, jonathanh, linux-gpio, devicetree,
linux-tegra, linux-kernel, Laxman Dewangan
NVIDIA Tegra124 and later SoCs support the multi-voltage level and
low power state of some of its IO pads. The IO pads can work in
the voltage of the 1.8V and 3.3V of IO power rail sources. When IO
interface are not used then IO pads can be configure in low power
state to reduce the power from that IO pads.
This series add the support of configuration of IO pad via pinctrl
framework. The io pad driver uses the tegra PMC interface.
---
This driver was sent earlier for review along with soc/tegra pmc
changes. During review, decided to first conclude in soc/tegra pmc
patches and then review this.
Thierry applied the pmc patches in the private tree
https://github.com/thierryreding/linux/tree/tegra186
and he wanted to have the patches for user of the new APIs so that
it can be pushed to mainline.
Sending the pinctrl driver. This needs Ack/reviewed from pinctrl subsystem
i.e. Linus Welleij to apply in the Thierry's T186 branch along with
PMC patches.
---
Changes from V1:
- use the regulator framework to get the IO voltage instead of table from
DT. The regulator handle is provided from DT.
Laxman Dewangan (2):
pinctrl: tegra: Add DT binding for io pads control
pinctrl: tegra: Add driver to configure voltage and power of io pads
.../bindings/pinctrl/nvidia,tegra-io-pad.txt | 112 +++++++
drivers/pinctrl/tegra/Kconfig | 12 +
drivers/pinctrl/tegra/Makefile | 1 +
drivers/pinctrl/tegra/pinctrl-tegra-io-pad.c | 369 +++++++++++++++++++++
include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h | 21 ++
5 files changed, 515 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/nvidia,tegra-io-pad.txt
create mode 100644 drivers/pinctrl/tegra/pinctrl-tegra-io-pad.c
create mode 100644 include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h
--
2.1.4
^ permalink raw reply
* Re: [Qemu-devel] [PATCH] nbd: Don't inf-loop on early EOF
From: Paolo Bonzini @ 2016-11-09 13:05 UTC (permalink / raw)
To: Eric Blake, Max Reitz, qemu-devel; +Cc: qemu-block
In-Reply-To: <5e7c4a2a-d2d4-7174-471a-d0a5232d2023@redhat.com>
On 07/11/2016 23:45, Eric Blake wrote:
> On 11/07/2016 04:22 PM, Max Reitz wrote:
>> On 07.11.2016 21:38, Eric Blake wrote:
>>> Commit 7d3123e converted a single read_sync() into a while loop
>>> that assumed that read_sync() would either make progress or give
>>> an error. But when the server hangs up early, the client sees
>>> EOF (a read_sync() of 0) and never makes progress, which in turn
>>> caused qemu-iotest './check -nbd 83' to go into an infinite loop.
>>>
>>> Rework the loop to accomodate reads cut short by EOF.
>>>
>>> Reported-by: Max Reitz <mreitz@redhat.com>
>>> Signed-off-by: Eric Blake <eblake@redhat.com>
>>> ---
>>> nbd/client.c | 13 +++++++------
>>> 1 file changed, 7 insertions(+), 6 deletions(-)
>>
>> Reviewed-by: Max Reitz <mreitz@redhat.com>
>>
>> But what about the server's nbd_negotiate_drop_sync()? It uses pretty
>> much the same code, so it seems susceptible to the same issue (only that
>> we don't have a test for that side).
>
> If so, that's an older bug (pre-existing back to at least 2.6?), so it
> should be a separate fix, if anything.
>
> I guess it's time to figure out how to test the server against
> ill-behaved clients...
Using afl perhaps?
Paolo
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.