at91 SoC separation

M. Warner Losh imp at bsdimp.com
Sun May 24 22:39:58 UTC 2009


In message: <164b4c9c0905241206s570a15b1ob6214e9505329ae at mail.gmail.com>
            Sylvestre Gallon <ccna.syl at gmail.com> writes:
: Hi,
: 
: I am currently working on the at91sam9261ek port for the
: Google Summer Of Code 2009.
: 
: Currently I work on how I could implement the at91sam9261ek
: most efficiently. I notice that all the at91 code could be at91
: System On Chip independent with some few changes.
: 
: The big work is to extract the SoC specific code in a separate file
: by SoC. It's what I tried to do on my perforce :
: 
: perforce repo :
: http://perforce.freebsd.org/depotTreeBrowser.cgi?FSPC=//depot/projects/soc2009/syl_usb/src/sys/arm/at91&HIDEDEL=NO
: 
: Changes that I've done :
: http://perforce.freebsd.org/changeList.cgi?FSPC=%2F%2Fdepot%2Fprojects%2Fsoc2009%2Fsyl_usb%2Fsrc%2Fsys%2Farm%2Fat91%2F...&USERS=syl&GROUPS=soc2009&ignore=GO!
: 
: One thing that continues to disturb me : On At91 SoC, the IPs and
: their registers are quite the same. The only big change that exists
: between these SoC are the base addresses for each IPs.  The different
: SoC generic drivers may need IPs base addresses to perform the
: mapping of registers. For the moment to not have some ugly
: #ifdef like :
: 
: #ifdef __AT91RM9200__
: #include <at91rm92reg.h>
: #elif __AT91SAM9261__
: #include <at91sam9261.h>
: #elfi __ANOTHER_SOC__
: #include <another_soc.h>
: #endif
: 
: I have created base address accessors in the SoC file. But I'm not
: sure I like that... Do you have some ideas to handle it in a better
: way ?
: 
: When All the code of at91 will be SoC independents It will be very
: easy to port any other at91 board (1 or 2 days of work by cpu).
: I have also access to a lot of atmel board, I live near Atmel French
: R&D  and know some people who work there who are ready to lend
: me boards with these SoC :
: 
: - at91sam9260
: - at91sam9261
: - at91sam9263
: - at91sam9rl
: - at91sam9m10 (not officially out, and not yet in Linux ;) )
: - at91cap9
: - ..
: 
: I'am open to all suggestions, it is important for me to implement
: the at91sam9261ek (and perhaps other) port the best way I can
: to have a chance to see it in current after the Google Summer Of
: Code :)


I've been thinking about the issues for a long time.  And there's a
number of interrelated problems.  All of them are related to the fact
that we have the core, SoC and board smashed into one file right now.
We really need to finish separating out the core support (it is mostly
done right now, except for some of the bus space stuff).  The SoC and
board support is all in at91.c, which really should be about
infrastructure not about boards...

First, you need to know what board you are on when you boot.  uboot
and others pass this information into the kernel using register r3,
IIRC.  So, there would need to be a way for the early boot code to
probe for one of a number of different boards.  For SoC, this could be
just one board compiled into the kernel (eg, you don't have run time
select), but Sam has done some work in this area on the xscale parts
you may be able to snag.

If we assume that there's a board init routine, we can assume that
init routine knows what kind of SoC is installed on the board and can
populate the atmelbus with the right devices by calling something like
at91rm9200_soc_init().  Then, that board routine can also do the
proper routing of the pins to the different peripherals as well,
possibly calling some generic peripheral init routines as well
(although that's a lot harder to arrange than you might otherwise
think given just how flexible these things are).  The board routine
would also be responsible for calling cninit() as well.

If we go this route, we can eliminate much of the #ifdef soup that you
were otherwise looking at doing.  The AT91RM9200 registers would be
defined in one place, but we'd try to use the base + offset approach
to isolate the number places that need this information.  That's one
of the problems with the current set of patches for the at91sam
boards: they just do ifdefs rather than do the proper refactoring to
get us the most amount of support.

So the typical board package would look something like:

int
kb9202_probe()
{
	if (arm_board_id_from_loader() != KB9202_BOARD_ID)
		return ENXIO;
	return 0;
}

int
kb9202_init()
{
	at91rm9200_soc_init();
	/*
	 * <insert the contents from board_kb920x.c's board_init()
	 * here>
	 */
	/*
	 * Map in the pmap entries needed on this board for flash, CF,
	 * etc
	 */
	/*
	 * Create some kind of descriptor to tell the SD card what GPIO
	 * pins are used for different things, what the MAC address
	 * of the board is, etc.  Maybe need one per driver and a list
	 * of them for this board
	 */
}

ARM_BOARD_TYPE(kb9202_probe, kb9202_init);

As an aside, you may also need to make the different boot loaders
pluggable as well, or maybe we would do that as part of another pass.
You could assume they were all uboot compatible or something...  Linux
defines a standard here, and we'd be wise to follow it...

Obviously, you'd need to rewrite arm_init as well to defer some of the
things it does now.  You'd need to move pmap init stuff to the
at91rm9200_soc_init(), except for the CF/FLASH stuff, which would move
to a board-level init.  Some of the mappings might need to change that
are done currently inline (which may mean we'd have to do some much
needed refactoring here).  Right now board_init is in a very special
place, and we'd likely need to move the cninit() into each board init
so that the boards could control which console was used.

There's also some ideas going around about being able to load hints
dynamically at run time and the foo_soc_init() and board_init routines
would just load them up correctly.  That's another orthogonal way to
move the tables out of at91rm9200_soc_init and into an easier to
manage text form, but at the expense of needing to add code to the
hints mechanism, and fight the bike-sheds that surround its
replacement.  So I'd frankly avoid this for the SoC project.  Getting
good separation is more important than having a perfect mechanism the
separation can use.

Those are just the top level ideas I have with respect to this port.
In fact, we could generalize this to all embedded boards since I
believe it scales well.  Linux does something similar, and to add a
new board is about a hundred lines, and a new SoC maybe ~400 more.

I think getting a good separation would be the key element to focus
on, as well as picking one or two other SoCs/boards to validate that
the design works and scales.  Make those the first priority.  Once you
have them in place and working, then if you've done things right
you'll be able to add all those other cool boards quickly, subject to
the availability of drivers and quirks for silicon bugs (oh, and free
time).

Comments?

Warner


More information about the freebsd-arm mailing list