Hi,
I'm developing on a CS5536 based board (ALIX.2D) and I'm trying to get access to the GPIO registers in order to set the LEDs on bootup.
However, I seem to miss an mandatory point when trying so. As a quick hack, I added these lines to the end of southbridge_init() in coreboot-v3/southbridge/amd/cs5536/cs5536.c:
outl(GPIOL_6_SET, GPIO_IO_BASE + GPIOL_OUTPUT_ENABLE); outl(GPIOL_6_CLEAR, GPIO_IO_BASE + GPIOL_OUTPUT_VALUE);
According to the schematics, GPIO6 is connected to one of the LEDs found on the board, but the GPIO level does not change. I tried reading back another GPIO but the READ_BACK register reads 0xffffffff, even though the uppermost 16 bits are supposed to be 0 always. So I assume I missed some basic point.
The MSR mapping should be set up at this point, as there are accesses to other GPIO related registers called from the same function.
Any pointers, anyone?
Thanks, Daniel
Daniel Mack wrote:
I'm developing on a CS5536 based board (ALIX.2D) and I'm trying to get access to the GPIO registers in order to set the LEDs on bootup.
Check out the 5536 data book on "Atomic Bit Programming" and/or look at the Linux LED driver for reference. To program the GPIOs you have to follow the algorithm outlined in 6.16.1.
//Peter
On Tue, Sep 22, 2009 at 4:56 AM, Peter Stuge peter@stuge.se wrote:
Daniel Mack wrote:
Check out the 5536 data book on "Atomic Bit Programming" and/or look at the Linux LED driver for reference. To program the GPIOs you have to follow the algorithm outlined in 6.16.1.
Yes, this is a pretty elegant idea the Geode guys created that is, sadly, not in anything else.
ron
On Tue, Sep 22, 2009 at 01:56:53PM +0200, Peter Stuge wrote:
Daniel Mack wrote:
I'm developing on a CS5536 based board (ALIX.2D) and I'm trying to get access to the GPIO registers in order to set the LEDs on bootup.
Check out the 5536 data book on "Atomic Bit Programming" and/or look at the Linux LED driver for reference. To program the GPIOs you have to follow the algorithm outlined in 6.16.1.
Hmm. I followed that guideline, and did the same thing than the Linux driver, but it still doesn't work. I only found one location from where I could successfully write to the GPIO registers, and that is hardware_stage1() in mainboard/pcengines/alix2c3/stage.c.
When moving the same code to southbridge_init() in southbridge/amd/cs5536/cs5536.c, the register accesses fail.
Also, when booting Linux, the LED driver does not work with coreboot for me. The register space mapping seems to be given up at some point on the way, but I can't figure out where and why yet. As I don't know coreboot's internals, I'd appreciate any pointer.
Thanks, Daniel
On Wed, Sep 23, 2009 at 06:03:38AM +0200, Daniel Mack wrote:
On Tue, Sep 22, 2009 at 01:56:53PM +0200, Peter Stuge wrote:
Check out the 5536 data book on "Atomic Bit Programming" and/or look at the Linux LED driver for reference. To program the GPIOs you have to follow the algorithm outlined in 6.16.1.
Hmm. I followed that guideline, and did the same thing than the Linux driver, but it still doesn't work. I only found one location from where I could successfully write to the GPIO registers, and that is hardware_stage1() in mainboard/pcengines/alix2c3/stage.c.
When moving the same code to southbridge_init() in southbridge/amd/cs5536/cs5536.c, the register accesses fail.
Also, when booting Linux, the LED driver does not work with coreboot for me. The register space mapping seems to be given up at some point on the way, but I can't figure out where and why yet. As I don't know coreboot's internals, I'd appreciate any pointer.
I traced a little further and implemented a cs5536_set_resources() which simply wraps the call to pci_set_resources(). GPIO registers are accessed ok before pci_set_resources() but fail after.
This is the output of print_resource_tree() of the device used:
(CB) PCI: 00:0f.0 links 0 child on link 0 NULL (CB) PCI: 00:0f.0 resource base 0 size 1000 align 0 gran 0 limit 0 flags e0000100 index 0 (CB) PCI: 00:0f.0 resource base 20b0 size 8 align 3 gran 3 limit ffff flags 40000100 index 10 (CB) PCI: 00:0f.0 resource base 1800 size 100 align 8 gran 8 limit ffff flags 40000100 index 14 (CB) PCI: 00:0f.0 resource base 2000 size 40 align 6 gran 6 limit ffff flags 40000100 index 18 (CB) PCI: 00:0f.0 resource base 2080 size 20 align 5 gran 5 limit ffff flags 40000100 index 1c (CB) PCI: 00:0f.0 resource base 1c00 size 80 align 7 gran 7 limit ffff flags 40000100 index 20 (CB) PCI: 00:0f.0 resource base 2040 size 40 align 6 gran 6 limit ffff flags 40000100 index 24
Any ideas?
Daniel
I traced a little further and implemented a cs5536_set_resources() which simply wraps the call to pci_set_resources(). GPIO registers are accessed ok before pci_set_resources() but fail after.
Sounds like the address where you access the resource is changing after resource allocation. You have a couple of options: 1. Use the new address after pci_set_resources 2. Don't use pci_set_resources to allocate that resource (Set up that resource as fixed)
I think #1 is the best, unless you have to have that address at a specific location.
This is the output of print_resource_tree() of the device used:
I don't know enough about it to know which of these resources is the one you're looking for, but you can look through the code to see where the GPIO registers are set up.
(CB) PCI: 00:0f.0 links 0 child on link 0 NULL (CB) PCI: 00:0f.0 resource base 0 size 1000 align 0 gran 0 limit 0 flags e0000100 index 0 (CB) PCI: 00:0f.0 resource base 20b0 size 8 align 3 gran 3 limit ffff flags 40000100 index 10 (CB) PCI: 00:0f.0 resource base 1800 size 100 align 8 gran 8 limit ffff flags 40000100 index 14 (CB) PCI: 00:0f.0 resource base 2000 size 40 align 6 gran 6 limit ffff flags 40000100 index 18 (CB) PCI: 00:0f.0 resource base 2080 size 20 align 5 gran 5 limit ffff flags 40000100 index 1c (CB) PCI: 00:0f.0 resource base 1c00 size 80 align 7 gran 7 limit ffff flags 40000100 index 20 (CB) PCI: 00:0f.0 resource base 2040 size 40 align 6 gran 6 limit ffff flags 40000100 index 24
Good luck, Myles
On Wed, Sep 23, 2009 at 06:03:38AM +0200, Daniel Mack wrote:
Also, when booting Linux, the LED driver does not work with coreboot for me.
Yeah, known issue. The linux kernel driver stupidly assumes that all firmware sets up the GPIOs at the same IO port. The kernel driver should look up the msr and then do the right thing, but it does not.
I think Peter Stuge may have a patch for the LED driver...
Thanks, Ward.
Ward Vandewege wrote:
I think Peter Stuge may have a patch for the LED driver...
If I do it's on a hard drive that I can't find anymore. It's not a terribly complex change, but the mere thought of cloning the led-2.6 tree is a little exhausting.
//Peter
Daniel Mack wrote:
Also, when booting Linux, the LED driver does not work with coreboot for me.
The issue is that the driver is using a hard coded base address rather than finding out what is actually programmed into the device, and because coreboot doesn't assign resources exactly like the factory BIOS, the driver can't find the hardware.
The driver should be improved to read the base address from the MSR, then it would work everywhere.
Another sad fact is that the driver scans the BIOS 0xf0000 segment for a particular string which is present in the factory BIOS, but not in coreboot. I believe there is an override.
You may find msrtool helpful since it knows a bit about Geode, although not nearly everything. It's good with the DIVIL and interrupts.
boot factory BIOS # msrtool -l -s file this saves a list of known MSRs along with their values into file
boot coreboot # msrtool -d file this shows decoded MSR differences between saved and current values
//Peter
On Wed, Sep 23, 2009 at 9:52 AM, Peter Stuge peter@stuge.se wrote:
Daniel Mack wrote:
Also, when booting Linux, the LED driver does not work with coreboot for me.
The issue is that the driver is using a hard coded base address rather than finding out what is actually programmed into the device, and because coreboot doesn't assign resources exactly like the factory BIOS, the driver can't find the hardware.
Depending on the address, that could be easy to fix. If it is below 0x1000 it is almost trivial.
Thanks, Myles
Myles Watson wrote:
Also, when booting Linux, the LED driver does not work with coreboot for me.
The issue is that the driver is using a hard coded base address rather than finding out what is actually programmed into the device, and because coreboot doesn't assign resources exactly like the factory BIOS, the driver can't find the hardware.
Depending on the address, that could be easy to fix. If it is below 0x1000 it is almost trivial.
It's at 6000 something, and I don't like to. I would much prefer the driver not make assumptions for no da^Wreason.
//Peter
On Wed, Sep 23, 2009 at 10:04 AM, Peter Stuge peter@stuge.se wrote:
Myles Watson wrote:
Also, when booting Linux, the LED driver does not work with coreboot for me.
The issue is that the driver is using a hard coded base address rather than finding out what is actually programmed into the device, and because coreboot doesn't assign resources exactly like the factory BIOS, the driver can't find the hardware.
Depending on the address, that could be easy to fix. If it is below 0x1000 it is almost trivial.
It's at 6000 something,
So that would be easy too.
and I don't like to. I would much prefer the driver not make assumptions for no da^Wreason.
Agreed. I guess it comes down to making changes where you can. Have you filed a bug report with the driver's authors?
Thanks, Myles
On Wed, Sep 23, 2009 at 06:04:57PM +0200, Peter Stuge wrote:
Myles Watson wrote:
Also, when booting Linux, the LED driver does not work with coreboot for me.
The issue is that the driver is using a hard coded base address rather than finding out what is actually programmed into the device, and because coreboot doesn't assign resources exactly like the factory BIOS, the driver can't find the hardware.
Depending on the address, that could be easy to fix. If it is below 0x1000 it is almost trivial.
It's at 6000 something, and I don't like to. I would much prefer the driver not make assumptions for no da^Wreason.
I think the driver assumes
CS5536_BASE = 0x06100
Thanks, Ward.
On Wed, Sep 23, 2009 at 06:04:57PM +0200, Peter Stuge wrote:
Myles Watson wrote:
Also, when booting Linux, the LED driver does not work with coreboot for me.
The issue is that the driver is using a hard coded base address rather than finding out what is actually programmed into the device, and because coreboot doesn't assign resources exactly like the factory BIOS, the driver can't find the hardware.
Depending on the address, that could be easy to fix. If it is below 0x1000 it is almost trivial.
It's at 6000 something, and I don't like to. I would much prefer the driver not make assumptions for no da^Wreason.
Could you outline which steps would need to be taken in order to find out the correct address to use? Any maybe a way to sany detect the precence of that function on the board? I might go ahead and send a patch for the driver then.
Thanks, Daniel
On Wed, Sep 23, 2009 at 1:10 PM, Daniel Mack daniel@caiaq.de wrote:
Could you outline which steps would need to be taken in order to find out the correct address to use? Any maybe a way to sany detect the precence of that function on the board? I might go ahead and send a patch for the driver then.
Not really an outline; it is just one MSR read. Take a look at the GPIO kernel driver:
http://lxr.linux.no/#linux+v2.6.31/drivers/char/cs5535_gpio.c#L188
Also, to correct the 0xF0000 scan ickiness, the proper way to detect a board revision is usually done by reading a PCI subvendor/subdevice ID too. I don't know if alix's non-coreboot BIOS does that properly.
On Wed, Sep 23, 2009 at 01:25:21PM -0400, Tom Sylla wrote:
On Wed, Sep 23, 2009 at 1:10 PM, Daniel Mack daniel@caiaq.de wrote:
Could you outline which steps would need to be taken in order to find out the correct address to use? Any maybe a way to sany detect the precence of that function on the board? I might go ahead and send a patch for the driver then.
Not really an outline; it is just one MSR read. Take a look at the GPIO kernel driver:
http://lxr.linux.no/#linux+v2.6.31/drivers/char/cs5535_gpio.c#L188
One attempt to do that I just sumbitted to LKML:
http://lkml.org/lkml/2009/10/5/426
Works fine here - let's see what the maintainers say.
Thanks for the pointers, Daniel
Daniel Mack wrote:
http://lkml.org/lkml/2009/10/5/426
Works fine here - let's see what the maintainers say.
gpio_base should maybe be 16 bit.
I'm not sure if strchr() can be assumed to work with '\0'.
//Peter