Notes for v3 ports
Note for those porting to v3
There are a lot of changes with v3, and they are basically good. I am doing the K8 port now, and I'd like to accumulate wisdom on this page. V3 really is very different and you don't realize it until you get into it.
The first thing to remember is that v2 is very much shaped by the romcc legacy. So you will see comments like this in v2 commits: "get more code compiling in both places" or some such.
What does this mean? It means, for example, that the function xyz(device_t) has to compile and work when device_t is a u32 (as in the ROM-based code that starts RAM) and as a struct device * (as in the RAM-based code). This schizophrenia pervades v2, even when it is not needed (as in v2 targets that can run with cache-as-ram). A lot of v2 code is still compiled twice.
This is especially true of the .h files with inlined functions. In v2, a lot of SMBUS functions are inlined, meaning they get compiled into the ROM and RAM code.
A dramatic change in v3 is that the ROM-based code can be called from the RAM-based code. This change in turn means that many support functions should be built into the ROM-based code, one example being the functions that support PCI config space.
Note: stage0 is very early assembly, and stage1 is ROM-based C code. For reasons of history the Makefiles call some code STAGE0, though we ought to call it STAGE1. Sorry.
What does this imply? In v3, you should plan to move code to stage1, and then mark certain functions as SHARED, so they can be called from stage2. Here's an example: on boards using the MCP55, I moved all the inlined SMBUS functions from mcp55_smbus.h to stage1_smbus.c. In the m57sli mainboard Makefile, the STAGE0 defines look like this:
STAGE0_MAINBOARD_OBJ := $(obj)/mainboard/$(MAINBOARDDIR)/stage1.o \ $(obj)/mainboard/$(MAINBOARDDIR)/option_table.o \ $(obj)/southbridge/nvidia/mcp55/stage1_smbus.o
So that the stage1_smbus code is built in. How do we make it shared? We add these lines to mcp55_smbus.h
#include <shared.h> SHARED(do_smbus_recv_byte, int, u16 smbus_io_base, u8 device); SHARED(do_smbus_send_byte, int, u16 smbus_io_base, u8 device, u8 val); SHARED(do_smbus_read_byte, int, u16 smbus_io_base, u8 device, u8 address); SHARED(do_smbus_write_byte, int, u16 smbus_io_base, u8 device, u8 address, u8 val); SHARED(enable_smbus, void, void);
Result: we only compile a lot of code once, with the same compiler, and it can be called from anywhere.