Changeset 1475 for trunk/bitbang_spi.c


Ignore:
Timestamp:
12/20/11 01:19:29 (5 months ago)
Author:
hailfinger
Message:

Have all programmer init functions register bus masters/programmers

All programmer types (Parallel, SPI, Opaque) now register themselves
into a generic programmer list and probing is now programmer-centric
instead of chip-centric.
Registering multiple SPI/... masters at the same time is now possible
without any problems. Handling multiple flash chips is still unchanged,
but now we have the infrastructure to deal with "dual BIOS" and "one
flash behind southbridge and one flash behind EC" sanely.

A nice side effect is that this patch kills quite a few global variables
and improves the situation for libflashrom.

Hint for developers:
struct {spi,par,opaque}_programmer now have a void *data pointer to
store any additional programmer-specific data, e.g. hardware
configuration info.

Note:
flashrom -f -c FOO -r forced_read.bin
does not work anymore. We have to find an architecturally clean way to
solve this.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@…>
Acked-by: Michael Karcher <flashrom@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/bitbang_spi.c

    r1474 r1475  
    2626#include "spi.h" 
    2727 
    28 /* Length of half a clock period in usecs. */ 
    29 static int bitbang_spi_half_period; 
    30  
    31 static const struct bitbang_spi_master *bitbang_spi_master = NULL; 
    32  
    3328/* Note that CS# is active low, so val=0 means the chip is active. */ 
    34 static void bitbang_spi_set_cs(int val) 
     29static void bitbang_spi_set_cs(const const struct bitbang_spi_master *master, int val) 
    3530{ 
    36         bitbang_spi_master->set_cs(val); 
     31        master->set_cs(val); 
    3732} 
    3833 
    39 static void bitbang_spi_set_sck(int val) 
     34static void bitbang_spi_set_sck(const const struct bitbang_spi_master *master, int val) 
    4035{ 
    41         bitbang_spi_master->set_sck(val); 
     36        master->set_sck(val); 
    4237} 
    4338 
    44 static void bitbang_spi_set_mosi(int val) 
     39static void bitbang_spi_set_mosi(const const struct bitbang_spi_master *master, int val) 
    4540{ 
    46         bitbang_spi_master->set_mosi(val); 
     41        master->set_mosi(val); 
    4742} 
    4843 
    49 static int bitbang_spi_get_miso(void) 
     44static int bitbang_spi_get_miso(const const struct bitbang_spi_master *master) 
    5045{ 
    51         return bitbang_spi_master->get_miso(); 
     46        return master->get_miso(); 
    5247} 
    5348 
    54 static void bitbang_spi_request_bus(void) 
     49static void bitbang_spi_request_bus(const const struct bitbang_spi_master *master) 
    5550{ 
    56         if (bitbang_spi_master->request_bus) 
    57                 bitbang_spi_master->request_bus(); 
     51        if (master->request_bus) 
     52                master->request_bus(); 
    5853} 
    5954 
    60 static void bitbang_spi_release_bus(void) 
     55static void bitbang_spi_release_bus(const const struct bitbang_spi_master *master) 
    6156{ 
    62         if (bitbang_spi_master->release_bus) 
    63                 bitbang_spi_master->release_bus(); 
     57        if (master->release_bus) 
     58                master->release_bus(); 
    6459} 
    6560 
     
    7974}; 
    8075 
    81 int bitbang_spi_init(const struct bitbang_spi_master *master, int halfperiod) 
     76#if 0 // until it is needed 
     77static int bitbang_spi_shutdown(const struct bitbang_spi_master *master) 
    8278{ 
     79        /* FIXME: Run bitbang_spi_release_bus here or per command? */ 
     80        return 0; 
     81} 
     82#endif 
     83 
     84int bitbang_spi_init(const struct bitbang_spi_master *master) 
     85{ 
     86        struct spi_programmer pgm = spi_programmer_bitbang; 
    8387        /* BITBANG_SPI_INVALID is 0, so if someone forgot to initialize ->type, 
    8488         * we catch it here. Same goes for missing initialization of bitbanging 
     
    8690         */ 
    8791        if (!master || master->type == BITBANG_SPI_INVALID || !master->set_cs || 
    88             !master->set_sck || !master->set_mosi || !master->get_miso) { 
     92            !master->set_sck || !master->set_mosi || !master->get_miso || 
     93            (master->request_bus && !master->release_bus) || 
     94            (!master->request_bus && master->release_bus)) { 
    8995                msg_perr("Incomplete SPI bitbang master setting!\n" 
    9096                         "Please report a bug at flashrom@flashrom.org\n"); 
    91                 return 1; 
    92         } 
    93         if (bitbang_spi_master) { 
    94                 msg_perr("SPI bitbang master already initialized!\n" 
    95                          "Please report a bug at flashrom@flashrom.org\n"); 
    96                 return 1; 
     97                return ERROR_FLASHROM_BUG; 
    9798        } 
    9899 
    99         bitbang_spi_master = master; 
    100         bitbang_spi_half_period = halfperiod; 
     100        pgm.data = master; 
     101        register_spi_programmer(&pgm); 
    101102 
    102         register_spi_programmer(&spi_programmer_bitbang); 
    103  
    104         /* FIXME: Run bitbang_spi_request_bus here or in programmer init? */ 
    105         bitbang_spi_set_cs(1); 
    106         bitbang_spi_set_sck(0); 
    107         bitbang_spi_set_mosi(0); 
     103        /* Only mess with the bus if we're sure nobody else uses it. */ 
     104        bitbang_spi_request_bus(master); 
     105        bitbang_spi_set_cs(master, 1); 
     106        bitbang_spi_set_sck(master, 0); 
     107        bitbang_spi_set_mosi(master, 0); 
     108        /* FIXME: Release SPI bus here and request it again for each command or 
     109         * don't release it now and only release it on programmer shutdown? 
     110         */ 
     111        bitbang_spi_release_bus(master); 
    108112        return 0; 
    109113} 
    110114 
    111 int bitbang_spi_shutdown(const struct bitbang_spi_master *master) 
    112 { 
    113         if (!bitbang_spi_master) { 
    114                 msg_perr("Shutting down an uninitialized SPI bitbang master!\n" 
    115                          "Please report a bug at flashrom@flashrom.org\n"); 
    116                 return 1; 
    117         } 
    118         if (master != bitbang_spi_master) { 
    119                 msg_perr("Shutting down a mismatched SPI bitbang master!\n" 
    120                          "Please report a bug at flashrom@flashrom.org\n"); 
    121                 return 1; 
    122         } 
    123  
    124         /* FIXME: Run bitbang_spi_release_bus here or per command? */ 
    125         bitbang_spi_master = NULL; 
    126         return 0; 
    127 } 
    128  
    129 static uint8_t bitbang_spi_readwrite_byte(uint8_t val) 
     115static uint8_t bitbang_spi_rw_byte(const struct bitbang_spi_master *master, 
     116                                   uint8_t val) 
    130117{ 
    131118        uint8_t ret = 0; 
     
    133120 
    134121        for (i = 7; i >= 0; i--) { 
    135                 bitbang_spi_set_mosi((val >> i) & 1); 
    136                 programmer_delay(bitbang_spi_half_period); 
    137                 bitbang_spi_set_sck(1); 
     122                bitbang_spi_set_mosi(master, (val >> i) & 1); 
     123                programmer_delay(master->half_period); 
     124                bitbang_spi_set_sck(master, 1); 
    138125                ret <<= 1; 
    139                 ret |= bitbang_spi_get_miso(); 
    140                 programmer_delay(bitbang_spi_half_period); 
    141                 bitbang_spi_set_sck(0); 
     126                ret |= bitbang_spi_get_miso(master); 
     127                programmer_delay(master->half_period); 
     128                bitbang_spi_set_sck(master, 0); 
    142129        } 
    143130        return ret; 
     
    150137{ 
    151138        int i; 
     139        const struct bitbang_spi_master *master = flash->pgm->spi.data; 
    152140 
    153141        /* FIXME: Run bitbang_spi_request_bus here or in programmer init? 
     
    155143         * programmer to use its own SPI engine for native accesses. 
    156144         */ 
    157         bitbang_spi_request_bus(); 
    158         bitbang_spi_set_cs(0); 
     145        bitbang_spi_request_bus(master); 
     146        bitbang_spi_set_cs(master, 0); 
    159147        for (i = 0; i < writecnt; i++) 
    160                 bitbang_spi_readwrite_byte(writearr[i]); 
     148                bitbang_spi_rw_byte(master, writearr[i]); 
    161149        for (i = 0; i < readcnt; i++) 
    162                 readarr[i] = bitbang_spi_readwrite_byte(0); 
     150                readarr[i] = bitbang_spi_rw_byte(master, 0); 
    163151 
    164         programmer_delay(bitbang_spi_half_period); 
    165         bitbang_spi_set_cs(1); 
    166         programmer_delay(bitbang_spi_half_period); 
     152        programmer_delay(master->half_period); 
     153        bitbang_spi_set_cs(master, 1); 
     154        programmer_delay(master->half_period); 
    167155        /* FIXME: Run bitbang_spi_release_bus here or in programmer init? */ 
    168         bitbang_spi_release_bus(); 
     156        bitbang_spi_release_bus(master); 
    169157 
    170158        return 0; 
Note: See TracChangeset for help on using the changeset viewer.