| The U-Boot Driver Model Project |
| =============================== |
| SPI analysis |
| ============ |
| Viktor Krivak <viktor.krivak@gmail.com> |
| 2012-03-03 |
| |
| I) Overview |
| ----------- |
| |
| 1) The SPI driver |
| ----------------- |
| |
| At this moment U-Boot provides standard API that consist of 7 functions: |
| |
| void spi_init(void); |
| struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, |
| unsigned int max_hz, unsigned int mode); |
| void spi_free_slave(struct spi_slave *slave); |
| int spi_claim_bus(struct spi_slave *slave); |
| void spi_release_bus(struct spi_slave *slave); |
| int spi_xfer(struct spi_slave *slave, unsigned int bitlen, |
| const void *dout, void *din, unsigned long flags); |
| int spi_cs_is_valid(unsigned int bus, unsigned int cs); |
| void spi_cs_activate(struct spi_slave *slave); |
| void spi_cs_deactivate(struct spi_slave *slave); |
| void spi_set_speed(struct spi_slave *slave, uint hz); |
| |
| Method spi_init() is usually empty. All necessary configuration are sets by |
| spi_setup_slave(). But this configuration is usually stored only in memory. |
| No real hardware sets are made. All hardware settings are provided by method |
| spi_claim_bus(). This method claims the bus and it can't be claimed again |
| until it's release. That's mean all calls of method spi_claim_bus() will |
| fail. But lots of cpu implementation don't meet this behaviour. |
| Method spi_release_bus() does exact opposite. It release bus directly by |
| some hardware sets. spi_free_slave() only free memory allocated by |
| spi_setup_slave(). Method spi_xfer() do actually read and write operation |
| throw specified bus and cs. Other methods are self explanatory. |
| |
| 2) Current limitations |
| ---------------------- |
| |
| Theoretically at this moment api allows use more then one bus per device at |
| the time. But in real this can be achieved only when all buses have their |
| own base addresses in memory. |
| |
| |
| II) Approach |
| ------------ |
| |
| 1) Claiming bus |
| --------------- |
| |
| The current api cannot be used because struct spi_slave have to be in |
| private data. In that case user are prohibited to use different bus on one |
| device at same time. But when base memory address for bus are different. |
| It's possible make more instance of this driver. Otherwise it can't can be |
| done because of hardware limitation. |
| |
| 2) API change |
| ------------- |
| |
| Method spi_init() is moved to probe. Methods spi_setup_slave() and |
| spi_claim_bus() are joined to one method. This method checks if desired bus |
| exists and is available then configure necessary hardware and claims bus. |
| Method spi_release_bus() and spi_free_slave() are also joined to meet this |
| new approach. Other function remain same. Only struct spi_slave was change |
| to instance. |
| |
| struct ops { |
| int (*spi_request_bus)(struct instance *i, unsigned int bus, |
| unsigned int cs, unsigned int max_hz, |
| unsigned int mode); |
| void (*spi_release_bus)(struct instance *i); |
| int (*spi_xfer) (struct instance *i, unsigned int bitlen, |
| const void *dout, void *din, unsigned long flags); |
| int (*spi_cs_is_valid)(struct instance *i, unsigned int bus, |
| unsigned int cs); |
| void (*spi_cs_activate)(struct instance *i); |
| void (*spi_cs_deactivate)(struct instance *i); |
| void (*spi_set_speed)(struct instance *i, uint hz); |
| } |
| |
| 3) Legacy API |
| ------------- |
| |
| To easy conversion of the whole driver. Original and new api can exist next |
| to each other. New API is designed to be only a wrapper that extracts |
| necessary information from private_data and use old api. When driver can |
| use more than one bus at the time. New API require multiple instance. One |
| for each bus. In this case spi_slave have to be copied in each instance. |
| |
| 4) Conversion TIME-LINE |
| ----------------------- |
| |
| To prevent build corruption api conversion have to be processed in several |
| independent steps. In first step all old API methods are renamed. After that |
| new API and core function are implemented. Next step is conversion of all |
| board init methods to set platform data. After all these steps it is possible |
| to start conversion of all remaining calls. This procedure guarantees that |
| build procedure and binaries are never broken. |
| |
| III) Analysis of in-tree drivers |
| -------------------------------- |
| |
| altera_spi.c |
| ------------ |
| All methods have designated structure. Simple conversion possible. |
| |
| andes_spi.c |
| ----------- |
| All methods have designated structure. Simple conversion possible. |
| |
| andes_spi.h |
| ----------- |
| Support file for andes_spi.c. No conversion is needed. |
| |
| armada100_spi.c |
| --------------- |
| All methods have designated structure. Simple conversion possible. |
| |
| atmel_dataflash_spi.c |
| --------------------- |
| Wrong placement. Will be moved to another location. |
| |
| atmel_spi.c |
| ----------- |
| Supports more than one bus. Need some minor change. |
| |
| atmel_spi.h |
| ----------- |
| Support file for andes_spi.c. No conversion is needed. |
| |
| bfin_spi.c |
| ---------- |
| Supports more than one bus. Need some minor change. |
| |
| cf_spi.c |
| -------- |
| Cooperate with some cpu specific methods from other files. Hard conversion. |
| |
| davinci_spi.c |
| ------------- |
| All methods have designated structure. Simple conversion possible. |
| |
| davinci_spi.h |
| ------------- |
| Support file for davinci_spi.h. No conversion is needed. |
| |
| fsl_espi.c |
| ---------- |
| All methods have designated structure. Simple conversion possible. |
| |
| kirkwood_spi.c |
| -------------- |
| All methods have designated structure. Simple conversion possible. |
| |
| mpc8xxx_spi.c |
| ------------- |
| All methods have designated structure. Simple conversion possible. |
| |
| mpc52xx_spi.c |
| ------------- |
| All methods have designated structure. Simple conversion possible. |
| |
| mxc_spi.c |
| --------- |
| All methods have designated structure. Simple conversion possible. |
| |
| mxs_spi.c |
| --------- |
| All methods have designated structure. Simple conversion possible. |
| |
| oc_tiny_spi.c |
| ------------- |
| Supports more than one bus. Need some minor change. |
| |
| omap3_spi.c |
| ----------- |
| Supports more than one bus. Need some minor change. |
| |
| omap3_spi.h |
| ----------- |
| Support file for omap3_spi.c. No conversion is needed. |
| |
| sh_spi.c |
| -------- |
| All methods have designated structure. Simple conversion possible. |
| |
| sh_spi.h |
| -------- |
| Support file for sh_spi.h. No conversion is needed. |
| |
| soft_spi.c |
| ---------- |
| Use many board specific method linked from other files. Need careful debugging. |
| |
| tegra2_spi.c |
| ------------ |
| Some hardware specific problem when releasing bus. |