Re: [PATCH 7/8] efi: clocksoure: use event for timer

2017-03-13 Thread Jean-Christophe PLAGNIOL-VILLARD

> On 13 Mar 2017, at 6:30 PM, Michael Olbrich  wrote:
> 
> On Mon, Feb 27, 2017 at 11:19:29AM +0100, Jean-Christophe PLAGNIOL-VILLARD 
> wrote:
>> with this we can be hw generic
>> 
>> If the EFI implement timestamp protocol we could use instead of event
>> but even EDK2 Never Ever compile it for any target.
>> 
>> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD 
>> ---
>> common/efi/efi.c |   8 
>> drivers/clocksource/Kconfig  |   4 ++
>> drivers/clocksource/Makefile |   1 +
>> drivers/clocksource/efi.c| 110 
>> +++
>> 4 files changed, 123 insertions(+)
>> create mode 100644 drivers/clocksource/efi.c
>> 
>> diff --git a/common/efi/efi.c b/common/efi/efi.c
>> index 4b589b600..05c58250f 100644
>> --- a/common/efi/efi.c
>> +++ b/common/efi/efi.c
>> @@ -353,6 +353,14 @@ efi_status_t efi_main(efi_handle_t image, 
>> efi_system_table_t *sys_table)
>>  return EFI_SUCCESS;
>> }
>> 
>> +static int efi_core_init(void)
>> +{
>> +struct device_d *dev = device_alloc("efi-cs", DEVICE_ID_SINGLE);
>> +
>> +return platform_device_register(dev);
>> +}
>> +core_initcall(efi_core_init);
>> +
>> static int efi_postcore_init(void)
>> {
>>  char *uuid;
>> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
>> index 9b7f0a9d7..b12a85403 100644
>> --- a/drivers/clocksource/Kconfig
>> +++ b/drivers/clocksource/Kconfig
>> @@ -34,6 +34,10 @@ config CLOCKSOURCE_DUMMY_RATE
>>The option CONFIG_CLOCKSOURCE_DUMMY_RATE is used to adjust this 
>> clocksource.
>>The bigger rate valuest makes clocksource "faster".
>> 
>> +config CLOCKSOURCE_EFI
>> +bool "Generic EFI Driver"
>> +depends on EFI_BOOTUP
>> +
>> config CLOCKSOURCE_EFI_X86
>>  bool "EFI X86 HW driver"
>>  depends on EFI_BOOTUP && X86
>> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
>> index 1fd18296e..f69b33d0b 100644
>> --- a/drivers/clocksource/Makefile
>> +++ b/drivers/clocksource/Makefile
>> @@ -3,6 +3,7 @@ obj-$(CONFIG_ARM_SMP_TWD) += arm_smp_twd.o
>> obj-$(CONFIG_CLOCKSOURCE_BCM283X) += bcm2835.o
>> obj-$(CONFIG_CLOCKSOURCE_CLPS711X) += clps711x.o
>> obj-$(CONFIG_CLOCKSOURCE_DIGIC)   += digic.o
>> +obj-$(CONFIG_CLOCKSOURCE_EFI) += efi.o
>> obj-$(CONFIG_CLOCKSOURCE_EFI_X86) += efi_x86.o
>> obj-$(CONFIG_CLOCKSOURCE_MVEBU)   += mvebu.o
>> obj-$(CONFIG_CLOCKSOURCE_NOMADIK) += nomadik.o
>> diff --git a/drivers/clocksource/efi.c b/drivers/clocksource/efi.c
>> new file mode 100644
>> index 0..df65dd86c
>> --- /dev/null
>> +++ b/drivers/clocksource/efi.c
>> @@ -0,0 +1,110 @@
>> +/*
>> + * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD 
>> 
>> + *
>> + * Under GPL v2
>> + */
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +
>> +static uint64_t ticks = 1;
>> +static void *efi_cs_evt;
>> +
>> +static uint64_t efi_cs_read(void)
>> +{
>> +return ticks;
>> +}
>> +
>> +static void efi_cs_inc(void *event, void *ctx)
>> +{
>> +ticks++;
>> +}
>> +
>> +/* count ticks during a 1dms */
>> +static uint64_t ticks_freq(void)
>> +{
>> +uint64_t ticks_start, ticks_end;
>> +
>> +ticks_start = ticks;
>> +BS->stall(1000);
>> +ticks_end = ticks;
>> +
>> +return (ticks_end - ticks_start) * 1000;
>> +}
>> +
>> +/* count ticks during a 20ms delay as on qemu x86_64 the max is 100Hz */
>> +static uint64_t ticks_freq_x86(void)
>> +{
>> +uint64_t ticks_start, ticks_end;
>> +
>> +ticks_start = ticks;
>> +BS->stall(20 * 1000);
>> +ticks_end = ticks;
>> +
>> +return (ticks_end - ticks_start) * 50;
>> +}
>> +
>> +static int efi_cs_init(struct clocksource *cs)
>> +{
>> +efi_status_t efiret;
>> +uint64_t freq;
>> +
>> +efiret = BS->create_event(EFI_EVT_TIMER | EFI_EVT_NOTIFY_SIGNAL,
>> +EFI_TPL_CALLBACK, efi_cs_inc, NULL, _cs_evt);
>> +
>> +if (EFI_ERROR(efiret))
>> +return -efi_errno(efiret);
>> +
>> +efiret = BS->set_timer(efi_cs_evt, EFI_TIMER_PERIODIC, 10);
>> +if (EFI_ERROR(efiret)) {
>> +BS->close_event(efi_cs_evt);
>> +return -efi_errno(efiret);
>> +}
>> +
>> +freq = 1000 * 1000;
>> +if (ticks_freq() < 800 * 1000) {
>> +uint64_t nb_100ns;
>> +
>> +freq = ticks_freq_x86();
> 
> This needs a sanity ckeck. On one hardware that I have here 'freq' is often
> (but not always) zero.
> 

Really :(

please send a patch

FYI on x86 this generic Timer will replace at runtime by the efi_x86 that use 
HW IP
directly

Best Regards,
J.
___
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


Re: [PATCH 7/8] efi: clocksoure: use event for timer

2017-03-13 Thread Michael Olbrich
On Mon, Feb 27, 2017 at 11:19:29AM +0100, Jean-Christophe PLAGNIOL-VILLARD 
wrote:
> with this we can be hw generic
> 
> If the EFI implement timestamp protocol we could use instead of event
> but even EDK2 Never Ever compile it for any target.
> 
> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD 
> ---
>  common/efi/efi.c |   8 
>  drivers/clocksource/Kconfig  |   4 ++
>  drivers/clocksource/Makefile |   1 +
>  drivers/clocksource/efi.c| 110 
> +++
>  4 files changed, 123 insertions(+)
>  create mode 100644 drivers/clocksource/efi.c
> 
> diff --git a/common/efi/efi.c b/common/efi/efi.c
> index 4b589b600..05c58250f 100644
> --- a/common/efi/efi.c
> +++ b/common/efi/efi.c
> @@ -353,6 +353,14 @@ efi_status_t efi_main(efi_handle_t image, 
> efi_system_table_t *sys_table)
>   return EFI_SUCCESS;
>  }
>  
> +static int efi_core_init(void)
> +{
> + struct device_d *dev = device_alloc("efi-cs", DEVICE_ID_SINGLE);
> +
> + return platform_device_register(dev);
> +}
> +core_initcall(efi_core_init);
> +
>  static int efi_postcore_init(void)
>  {
>   char *uuid;
> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
> index 9b7f0a9d7..b12a85403 100644
> --- a/drivers/clocksource/Kconfig
> +++ b/drivers/clocksource/Kconfig
> @@ -34,6 +34,10 @@ config CLOCKSOURCE_DUMMY_RATE
> The option CONFIG_CLOCKSOURCE_DUMMY_RATE is used to adjust this 
> clocksource.
> The bigger rate valuest makes clocksource "faster".
>  
> +config CLOCKSOURCE_EFI
> + bool "Generic EFI Driver"
> + depends on EFI_BOOTUP
> +
>  config CLOCKSOURCE_EFI_X86
>   bool "EFI X86 HW driver"
>   depends on EFI_BOOTUP && X86
> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
> index 1fd18296e..f69b33d0b 100644
> --- a/drivers/clocksource/Makefile
> +++ b/drivers/clocksource/Makefile
> @@ -3,6 +3,7 @@ obj-$(CONFIG_ARM_SMP_TWD) += arm_smp_twd.o
>  obj-$(CONFIG_CLOCKSOURCE_BCM283X) += bcm2835.o
>  obj-$(CONFIG_CLOCKSOURCE_CLPS711X) += clps711x.o
>  obj-$(CONFIG_CLOCKSOURCE_DIGIC)   += digic.o
> +obj-$(CONFIG_CLOCKSOURCE_EFI) += efi.o
>  obj-$(CONFIG_CLOCKSOURCE_EFI_X86) += efi_x86.o
>  obj-$(CONFIG_CLOCKSOURCE_MVEBU)   += mvebu.o
>  obj-$(CONFIG_CLOCKSOURCE_NOMADIK) += nomadik.o
> diff --git a/drivers/clocksource/efi.c b/drivers/clocksource/efi.c
> new file mode 100644
> index 0..df65dd86c
> --- /dev/null
> +++ b/drivers/clocksource/efi.c
> @@ -0,0 +1,110 @@
> +/*
> + * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD 
> + *
> + * Under GPL v2
> + */
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +static uint64_t ticks = 1;
> +static void *efi_cs_evt;
> +
> +static uint64_t efi_cs_read(void)
> +{
> + return ticks;
> +}
> +
> +static void efi_cs_inc(void *event, void *ctx)
> +{
> + ticks++;
> +}
> +
> +/* count ticks during a 1dms */
> +static uint64_t ticks_freq(void)
> +{
> + uint64_t ticks_start, ticks_end;
> +
> + ticks_start = ticks;
> + BS->stall(1000);
> + ticks_end = ticks;
> +
> + return (ticks_end - ticks_start) * 1000;
> +}
> +
> +/* count ticks during a 20ms delay as on qemu x86_64 the max is 100Hz */
> +static uint64_t ticks_freq_x86(void)
> +{
> + uint64_t ticks_start, ticks_end;
> +
> + ticks_start = ticks;
> + BS->stall(20 * 1000);
> + ticks_end = ticks;
> +
> + return (ticks_end - ticks_start) * 50;
> +}
> +
> +static int efi_cs_init(struct clocksource *cs)
> +{
> + efi_status_t efiret;
> + uint64_t freq;
> +
> + efiret = BS->create_event(EFI_EVT_TIMER | EFI_EVT_NOTIFY_SIGNAL,
> + EFI_TPL_CALLBACK, efi_cs_inc, NULL, _cs_evt);
> +
> + if (EFI_ERROR(efiret))
> + return -efi_errno(efiret);
> +
> + efiret = BS->set_timer(efi_cs_evt, EFI_TIMER_PERIODIC, 10);
> + if (EFI_ERROR(efiret)) {
> + BS->close_event(efi_cs_evt);
> + return -efi_errno(efiret);
> + }
> +
> + freq = 1000 * 1000;
> + if (ticks_freq() < 800 * 1000) {
> + uint64_t nb_100ns;
> +
> + freq = ticks_freq_x86();

This needs a sanity ckeck. On one hardware that I have here 'freq' is often
(but not always) zero.

Michael

> + nb_100ns = 10 * 1000 * 1000 / freq;
> + pr_warn("EFI Event timer too slow freq = %llu Hz\n", freq);
> + efiret = BS->set_timer(efi_cs_evt, EFI_TIMER_PERIODIC, 
> nb_100ns);
> + if (EFI_ERROR(efiret)) {
> + BS->close_event(efi_cs_evt);
> + return -efi_errno(efiret);
> + }
> + }
> +
> + cs->mult = clocksource_hz2mult(freq, cs->shift);
> +
> + return 0;
> +}
> +
> +static struct clocksource efi_cs = {
> + .read   = efi_cs_read,
> + .mask   = CLOCKSOURCE_MASK(64),
> + .shift  = 0,
> + .init   = efi_cs_init,
> +};
> +
> 

[PATCH 7/8] efi: clocksoure: use event for timer

2017-02-27 Thread Jean-Christophe PLAGNIOL-VILLARD
with this we can be hw generic

If the EFI implement timestamp protocol we could use instead of event
but even EDK2 Never Ever compile it for any target.

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD 
---
 common/efi/efi.c |   8 
 drivers/clocksource/Kconfig  |   4 ++
 drivers/clocksource/Makefile |   1 +
 drivers/clocksource/efi.c| 110 +++
 4 files changed, 123 insertions(+)
 create mode 100644 drivers/clocksource/efi.c

diff --git a/common/efi/efi.c b/common/efi/efi.c
index 4b589b600..05c58250f 100644
--- a/common/efi/efi.c
+++ b/common/efi/efi.c
@@ -353,6 +353,14 @@ efi_status_t efi_main(efi_handle_t image, 
efi_system_table_t *sys_table)
return EFI_SUCCESS;
 }
 
+static int efi_core_init(void)
+{
+   struct device_d *dev = device_alloc("efi-cs", DEVICE_ID_SINGLE);
+
+   return platform_device_register(dev);
+}
+core_initcall(efi_core_init);
+
 static int efi_postcore_init(void)
 {
char *uuid;
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 9b7f0a9d7..b12a85403 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -34,6 +34,10 @@ config CLOCKSOURCE_DUMMY_RATE
  The option CONFIG_CLOCKSOURCE_DUMMY_RATE is used to adjust this 
clocksource.
  The bigger rate valuest makes clocksource "faster".
 
+config CLOCKSOURCE_EFI
+   bool "Generic EFI Driver"
+   depends on EFI_BOOTUP
+
 config CLOCKSOURCE_EFI_X86
bool "EFI X86 HW driver"
depends on EFI_BOOTUP && X86
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 1fd18296e..f69b33d0b 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_ARM_SMP_TWD) += arm_smp_twd.o
 obj-$(CONFIG_CLOCKSOURCE_BCM283X) += bcm2835.o
 obj-$(CONFIG_CLOCKSOURCE_CLPS711X) += clps711x.o
 obj-$(CONFIG_CLOCKSOURCE_DIGIC)   += digic.o
+obj-$(CONFIG_CLOCKSOURCE_EFI) += efi.o
 obj-$(CONFIG_CLOCKSOURCE_EFI_X86) += efi_x86.o
 obj-$(CONFIG_CLOCKSOURCE_MVEBU)   += mvebu.o
 obj-$(CONFIG_CLOCKSOURCE_NOMADIK) += nomadik.o
diff --git a/drivers/clocksource/efi.c b/drivers/clocksource/efi.c
new file mode 100644
index 0..df65dd86c
--- /dev/null
+++ b/drivers/clocksource/efi.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD 
+ *
+ * Under GPL v2
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static uint64_t ticks = 1;
+static void *efi_cs_evt;
+
+static uint64_t efi_cs_read(void)
+{
+   return ticks;
+}
+
+static void efi_cs_inc(void *event, void *ctx)
+{
+   ticks++;
+}
+
+/* count ticks during a 1dms */
+static uint64_t ticks_freq(void)
+{
+   uint64_t ticks_start, ticks_end;
+
+   ticks_start = ticks;
+   BS->stall(1000);
+   ticks_end = ticks;
+
+   return (ticks_end - ticks_start) * 1000;
+}
+
+/* count ticks during a 20ms delay as on qemu x86_64 the max is 100Hz */
+static uint64_t ticks_freq_x86(void)
+{
+   uint64_t ticks_start, ticks_end;
+
+   ticks_start = ticks;
+   BS->stall(20 * 1000);
+   ticks_end = ticks;
+
+   return (ticks_end - ticks_start) * 50;
+}
+
+static int efi_cs_init(struct clocksource *cs)
+{
+   efi_status_t efiret;
+   uint64_t freq;
+
+   efiret = BS->create_event(EFI_EVT_TIMER | EFI_EVT_NOTIFY_SIGNAL,
+   EFI_TPL_CALLBACK, efi_cs_inc, NULL, _cs_evt);
+
+   if (EFI_ERROR(efiret))
+   return -efi_errno(efiret);
+
+   efiret = BS->set_timer(efi_cs_evt, EFI_TIMER_PERIODIC, 10);
+   if (EFI_ERROR(efiret)) {
+   BS->close_event(efi_cs_evt);
+   return -efi_errno(efiret);
+   }
+
+   freq = 1000 * 1000;
+   if (ticks_freq() < 800 * 1000) {
+   uint64_t nb_100ns;
+
+   freq = ticks_freq_x86();
+   nb_100ns = 10 * 1000 * 1000 / freq;
+   pr_warn("EFI Event timer too slow freq = %llu Hz\n", freq);
+   efiret = BS->set_timer(efi_cs_evt, EFI_TIMER_PERIODIC, 
nb_100ns);
+   if (EFI_ERROR(efiret)) {
+   BS->close_event(efi_cs_evt);
+   return -efi_errno(efiret);
+   }
+   }
+
+   cs->mult = clocksource_hz2mult(freq, cs->shift);
+
+   return 0;
+}
+
+static struct clocksource efi_cs = {
+   .read   = efi_cs_read,
+   .mask   = CLOCKSOURCE_MASK(64),
+   .shift  = 0,
+   .init   = efi_cs_init,
+};
+
+static int efi_cs_probe(struct device_d *dev)
+{
+   return init_clock(_cs);
+}
+
+static struct driver_d efi_cs_driver = {
+   .name = "efi-cs",
+   .probe = efi_cs_probe,
+};
+
+static int efi_cs_initcall(void)
+{
+   return platform_driver_register(_cs_driver);
+}
+/* for efi the time must be init at core initcall level */
+late_initcall(efi_cs_initcall);
-- 
2.11.0