PPC chips support

The PPC startup library has been modified in order to:

The new routines and data variables all begin with ppcv_ for PPC variant, and are separated out into one function or data variable per source file. This separation allows maximum code reuse and minimum code duplication.

There are two new data structures:

The first is:

    struct ppcv_chip {
        unsigned short  chip;
        uint8_t         paddr_bits;
        uint8_t         cache_lsize;
        unsigned short  icache_lines;
        unsigned short  dcache_lines;
        unsigned        cpu_flags;
        unsigned        pretend_cpu;
        const char      *name;
        void            (*setup)(void);
    };

Every supported CPU has a statically initialized variable of this type (in its own source file, e.g. <ppvc_chip_603e7.c>).

If the chip field matches the upper 16 bits of the PVR register, this ppcv_chip structure is selected and the pccv global variable in the library is pointed at it. Only the upper 16 bits are checked so you can use the constants like PPC_750 defined in <ppc/cpu.h> when initializing the field.

The paddr_bits field is the number of physical address lines on the chip, usually 32.

The cache_lsize field is the number of bits in a cache line size of the chip, usually 5, but sometimes 4.

The icache_lines and dcache_lines are the number of lines in the instruction and data cache, respectively.

The cpu_flags field holds the PPC_CPU_* flag constants from <ppc/syspage.h> that are appropriate for this CPU. Note that the older startups sometimes left out flags like PPC_CPU_HW_HT and depended on the kernel to check the PVR and turn them on if appropriate. This is no longer the case. The kernel will continue to turn on those bits if it detects an old style startup, but will NOT with a new style one.

The pretend_cpu field goes into the ppc_kerinfo_entry.pretend_cpu field of the system page and as before, it's used to tell the kernel that even though you don't know the PVR, you can act like it's the pretend one.

The name field is the string name of the CPU that gets put in the cpuinfo section.

The setup function is called when a particular ppcv_chip structure has been selected by the library as the one to use. It continues the library customization process by filling the second new structure.

The second data structure is:

struct ppcv_config {
    unsigned    family;
    void        (*cpuconfig1)(int cpu);
    void        (*cpuconfig2)(int cpu);
    void        (*cpuinfo)(struct cpuinfo_entry *cpu);
    void        (*qtime)(void);
    void        *(*map)(unsigned size, paddr_t phys,
                                   unsigned prot_flags);
    void        (*unmap)(void *);
    int         (*mmu_info)(enum mmu_info info, unsigned tlb);
//NYI: tlb_read/write
};

There's a single variable defined of this type in the library, called ppcv_config. The setup function identified by the selected ppcv_chip is responsible for filling in the fields with the appropriate routines for the chip. The variable is statically initialized with a set of do-nothing routines, so if a particular chip doesn't need something done in one spot (typically the cpuconfig[1/2] routines), the setup routine doesn't have to fill anything in).

The general design rules for the routines are that they should perform whatever chip-specific actions that they can perform that are not also board-specific. For example, the old startup main() functions would sometimes turn off data translation, since some IPLs turned it on. With the new startups this is handled automatically by the library. On the other hand, both the old and new startups call the ppc700_init_l2_cache() manually in main(), since the exact bits to put in the L2CR register are board-specific. The routines in the libraries should be modified to work with the IPL and initialize the CPU properly, rather than modifying the board-specific code to hack around it (e.g. the aforementioned disabling of data translation).

The setup routine might also initialize a couple of other freestanding variables that other support routines use to avoid them having to check the PVR value again (e.g. see the ppc600_set_clock_freqs() and ppcv_setup_7450() functions for an example).

The new startup (and kernel, when used with a new startup) no longer depends on the PVR to identify the chip family. Instead the "family" field is filled in with a PPC_FAMILY_* value from <ppc/syspage.h>. This is transferred to the ppc_kerinfo_entry.family field on the system page, which the kernel uses to verify that the right version of procnto is being used.

If the kernel sees a value of PPC_FAMILY_UNKNOWN (zero) in the system page, it assumes that an old style startup is being used and will attempt to determine the family (and cpuinfo->flags) fields on its own. DO NOT USE that feature with new startups.

Fill in the ppcv_config.family and ppcv_chip.cpu_flags field properly. The cpuconfig1 routine is used to configure the CPU for use in startup, and is called early before main() is called. For example, it makes sure that instruction and data translation is turned off, the exception table is pointed at low memory, etc. It's called once for every CPU in an SMP system, with the cpu parm indicating the CPU number being initialized.

The cpuconfig2 routine is called just before startup transfers control to the first bootstrap executable in the image file system. It configures the CPU for running in the bootstrap environment, e.g. turning on CPU-specific features such as HID0 and HID1 bits. Again it's called once per CPU in an SMP system with the cpu parm indicating which one.

The cpuinfo routine is called by init_one_cpuinfo() to fill in the cpuinfo_entry structure for each CPU. The qtime routine is called by init_qtime() to set up the qtime syspage section.

The map and unmap routines used to create/delete memory mappings for startup and callout use, are called by:

There's one more data variable to mention. This is ppcv_list, which is a statically initialized array of pointers to ppcv_chip structures. The default version of the variable in the library has a list of all the ppcv_chip variables defined by the library so, by default, the library is capable of handling any type of PPC chip.

By defining a ppcv_list variable in the board-specific directory and adding only the ppcv_chip_* variable(s) that can be used with that board, all the chip-specific code for the processors that can't possibly be there will be left out.

For example, the new shasta-ssc startup with the default ppcv_list is about 1 KB bigger than the old version. By restricting the ppcv_list to only ppcv_chip_750, the new startup drops to 1 KB smaller than the original.