* AMD Ryzen Embedded V1000 (V-Series APU)
* AMD Ryzen Embedded R1000 (R-Series APU)
* AMD EPYC Embedded E3000 (E-Series CPU)
See: https://www.amd.com/en/products/embedded-ryzen-series
See: https://www.amd.com/en/products/embedded-epyc-3000-series
The driver that you mentioned does not drive the watchdog on these platforms, and the driver I am submitting
does not exist in the upstream linux kernel. However linux implementation of this driver was shared by AMD
with us (Mentor).
See: https://git.yoctoproject.org/cgit/cgit.cgi/meta-amd/tree/meta-amd-bsp/recipes-kernel/amd-wdt/files
...and I implemented this driver for grub-efi bootloader.
...and I basically ported that over to efibootguard bootloader.
And yes, you're right. I should change the name to something more specific targetting these platforms.
But I'd need your suggestion on this for what you'd like for the efibootguard project.
Arsalan:
I'm on it!
> > +
> > +#define PCI_VENDOR_ID_AMD 0x1022
> > +
> > +/* #define AMD_WDT_DEBUG */
> > +
> > +static struct
> > +{
> > + UINT8 fired;
> > + UINTN base;
> > + EFI_PCI_IO *pci_io;
> > +} watchdog;
> > +
> > +static EFI_STATUS
> > +writel (UINT32 val, UINT32 addr)
>
> static EFI_STATUS writel(...)
>
> Please align your coding style to the rest of the project, specifically
> the watchdog drivers.
>
> > +{
> > +#ifdef AMD_WDT_DEBUG
> > + Print (L"\n- writel (%X, %X) ", val, addr);
> > +#endif
>
> Still needed? If so, wrap properly and have a single ifdef there and a
> DebugPrint or so in the code. But I suppose your code is beyond that
> point already.
>
Arsalan:
I found this extremely helpful in debugging.
Arsalan:
I did what AMD did for their kernel implementation of this watchdog driver.
Arsalan:
AMD themselves think that it is.
> > + val = readl (AMD_WDT_CONTROL(watchdog.base));
> > + val |= AMD_WDT_START_STOP_BIT;
>
> I think the kernel does more, please cross-check.
>
Arsalan:
I did what AMD did in their kernel implementation of this driver.
Arsalan:
Again, It's not for EFCH chipset. And it targets at least 3 different latest series of AMD chips at the moment
that I have personally tested this driver on, and we know 2 more series of AMD APUs/CPUs coming soon
that this driver will be potentially applicable to... but I'm not sure.
So what would you suggest as a name for this driver?
> > + watchdog.pci_io = pci_io;
> > +
> > + Print(L"Detected AMD Carrizo SMBus Watchdog Timer\n");
>
> And here you actually call Carrizo, though I'm not sure if that covers
> it better. It's just that "AMD" is too generic.
>
Arsalan:
Please suggest a name. I'm only copying AMD here: ---> #define PCI_DEVICE_ID_AMD_CARRIZO_SMBUS 0x790B
> > +
> > + watchdog.fired = amd_wdt_check_fired();
> > +
> > +#ifdef AMD_WDT_DEBUG
> > + Print(L"\nwatchdog.base = %X\n", watchdog.base);
> > + Print(L"watchdog.fired = %X\n", watchdog.fired);
> > +#endif
>
> Still needed? Wlhat for? If not, drop all the dead fired-related code.
>
Arsalan:
In grub, we used the fired status to allow the user to take many decissions based on watchdog.fired status in the grub.cfg.
So, it can be useful in the cfg files. Besides I just copied the kernel implementation of this driver... so...
I can remove this if you guys don't have any plans of having such functionality.
Arsalan:
Well, I'm pretty sure the watchdog does not start the countdown unless it is pingged after start cmd.
Tested this driver with and without the ping on 3 different AMD platforms... so...
Also, here's how AMD did it in their kernel implementation of this driver:
static int amd_wdt_start(struct watchdog_device *wdt_dev)
{
u32 val;
unsigned long flags;
/* Enable the watchdog timer */
spin_lock_irqsave(&wdt_lock, flags);
val = readl(AMD_WDT_CONTROL(wdtbase));
val |= AMD_WDT_START_STOP_BIT;
writel(val, AMD_WDT_CONTROL(wdtbase));
spin_unlock_irqrestore(&wdt_lock, flags);
/* Trigger the watchdog timer */
amd_wdt_ping(wdt_dev);
return 0;
}
> > + if (EFI_ERROR(status)) {
> > + Print(L"Error: amd_wdt_ping () failed.");
> > + return status;
> > + }
> > +
> > +/*
> > + * Following is an alternate easy way to set the watchdog
> > + * using the UEFI API.
> > + * This works only if watchdog driver is implemented in the
> > + * UEFI firmware on the machine.
> > + *
> > + * status = uefi_call_wrapper(BS->SetWatchdogTimer, 4,
> > + * timeout, 0, 0, NULL);
> > + */
>
> What is this?
>
Arsalan:
It's the holy grail of watchdogs in UEFI. We don't need this whole implemntation of watchdog
drivers if the driver is already implemented in the UEFI firmware... we can simply do this!
And the UEFI sets the watchdog up for is... I can remove it if you think it's not useful.
> > +
> > + Print(L"\nAMD Watchdog setup complete!\n");
>
> Not strictly needed - we will see error messages if that stage is not
> reached.
>
Arsalan:
Sure, I'll remove this.
Arsalan:
OK!
-
Arsalan
Mentor, a Siemens business.
Mentor Embedded Linux.
>> does not exist in the upstream linux kernel. However linux implementation of this driver was shared by AMD
>> with us (Mentor).
>
>What? It's not upstream?
>
>>
>> See: https://git.yoctoproject.org/cgit/cgit.cgi/meta-amd/tree/meta-amd-bsp/recipes-kernel/amd-wdt/files
>>
>
>A yocto layer... Folks, properly work towards upstream. This kernel
>driver apparently sits there for a year. This is no proper way of
>maintaining such code. If AMD didn't do their homework, fix it.
>
Arsalan:
Well that's not all... anyway, there is no point in discussing that...
>I didn't look into all the details of what is missing/diverging, but I
>predict from what I've seen they will be minimal. It should take you day
>to sort it out for good.
>
Arsalan:
I can only submit what I have worked on... something I can test on a physical machine.
I don't know EFCH or SB800 or SP5100... and I know EFCH driver does *not* work on the
platforms I mentioned earlier.
>> ...and I implemented this driver for grub-efi bootloader.
>>
>> See: https://git.yoctoproject.org/cgit/cgit.cgi/meta-amd/tree/common/mentor-swupdate/recipes-bsp/grub/amd-wdt?h=sumo
>>
>> ...and I basically ported that over to efibootguard bootloader.
>>
>> And yes, you're right. I should change the name to something more specific targetting these platforms.
>> But I'd need your suggestion on this for what you'd like for the efibootguard project.
>
>For EFI Boot Guard, I'm fine with a driver that has a similar, modern
>scope like your downstream kernel module plus what the kernel drives
>under the very same PCI ID. Give it a name that reflects that scope.
>
Arsalan:
I'll try to talk to AMD to find out what they call this watchdog, but in
case I can't, would it be OK if I renamed it to "amd_carrizo_smbus_wdt"?
Arsalan:
If you look at the code, you'll see a lot of calls to inb, outb, readl and writel functions.
If I remove the functions and use the code inside instead, the code will get only bigger.
Everything else is necessary apart from watchdog.fired bits. I'll remove that. It may not
be as compact as it can get, but it is clean.
Arsalan:
How do I access the revision in efibootguard watchdog driver init (constructor) to compare against?
>>>> + return EFI_UNSUPPORTED;
>>>> + }
>>>> +
>>>> + watchdog.base = AMD_ACPI_MMIO_BASE + AMD_WDT_MEM_MAP_OFFSET;
>>>
>>> Ok, this hard-coding actually limits us to embedded FCH chipset. Fine
>>> with me, but then we have a different scope and should reflect that in
>>> the driver name (amd-efch?).
>>>
>> Arsalan:
>> Again, It's not for EFCH chipset. And it targets at least 3 different latest series of AMD chips at the moment
>
>It *is* EFCH-derived, just compare the code.
>
Arsalan:
Sure! But I don't know EFCH and I know that that driver does not work on these latest platforms.
And I don't want to write a driver for an EFCH because I cannot test it.
>> that I have personally tested this driver on, and we know 2 more series of AMD APUs/CPUs coming soon
>> that this driver will be potentially applicable to... but I'm not sure.
>>
>> So what would you suggest as a name for this driver?
>
>Give me the docs and I can likely tell you.
>
Arsalan:
Working on it...
Arsalan:
Consider it done!
Arsalan:
I guess...
Arsalan:
Consider it gone!
>Or is this the UEFI boot services watchdog that terminates early during
>Linux boot? That's unfortunately a completely useless thing when it
>comes to A/B update monitoring.
>
Arsalan:
I'm not sure if I exactly got you here, but I want to share my experience with this
method that the underlying hardware wdt (at least for the platforms I mentioned)
that got configured was the same.
So whether efibootguard configures the wdt, or UEFI configures the wdt and then
dies, the hardware wdt gets configured... and it will pop! It does! I've tested it!
>Jan
>
>--
>Siemens AG, Corporate Technology, CT RDA IOT SES-DE
>Corporate Competence Center Embedded Linux
-