uboot/drivers/spi/fdt_spi.c
<<
>>
Prefs
   1/*
   2 * Common fdt based SPI driver front end
   3 *
   4 * Copyright (c) 2013 NVIDIA Corporation
   5 *
   6 * See file CREDITS for list of people who contributed to this
   7 * project.
   8 *
   9 * This software is licensed under the terms of the GNU General Public
  10 * License version 2, as published by the Free Software Foundation, and
  11 * may be copied, distributed, and modified under those terms.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24#include <common.h>
  25#include <malloc.h>
  26#include <asm/io.h>
  27#include <asm/gpio.h>
  28#include <asm/arch/clock.h>
  29#include <asm/arch-tegra/clk_rst.h>
  30#include <asm/arch-tegra20/tegra20_sflash.h>
  31#include <asm/arch-tegra20/tegra20_slink.h>
  32#include <asm/arch-tegra114/tegra114_spi.h>
  33#include <spi.h>
  34#include <fdtdec.h>
  35
  36DECLARE_GLOBAL_DATA_PTR;
  37
  38struct fdt_spi_driver {
  39        int compat;
  40        int max_ctrls;
  41        int (*init)(int *node_list, int count);
  42        int (*claim_bus)(struct spi_slave *slave);
  43        int (*release_bus)(struct spi_slave *slave);
  44        int (*cs_is_valid)(unsigned int bus, unsigned int cs);
  45        struct spi_slave *(*setup_slave)(unsigned int bus, unsigned int cs,
  46                                        unsigned int max_hz, unsigned int mode);
  47        void (*free_slave)(struct spi_slave *slave);
  48        void (*cs_activate)(struct spi_slave *slave);
  49        void (*cs_deactivate)(struct spi_slave *slave);
  50        int (*xfer)(struct spi_slave *slave, unsigned int bitlen,
  51                    const void *data_out, void *data_in, unsigned long flags);
  52};
  53
  54static struct fdt_spi_driver fdt_spi_drivers[] = {
  55#ifdef CONFIG_TEGRA20_SFLASH
  56        {
  57                .compat         = COMPAT_NVIDIA_TEGRA20_SFLASH,
  58                .max_ctrls      = 1,
  59                .init           = tegra20_spi_init,
  60                .claim_bus      = tegra20_spi_claim_bus,
  61                .cs_is_valid    = tegra20_spi_cs_is_valid,
  62                .setup_slave    = tegra20_spi_setup_slave,
  63                .free_slave     = tegra20_spi_free_slave,
  64                .cs_activate    = tegra20_spi_cs_activate,
  65                .cs_deactivate  = tegra20_spi_cs_deactivate,
  66                .xfer           = tegra20_spi_xfer,
  67        },
  68#endif
  69#ifdef CONFIG_TEGRA20_SLINK
  70        {
  71                .compat         = COMPAT_NVIDIA_TEGRA20_SLINK,
  72                .max_ctrls      = CONFIG_TEGRA_SLINK_CTRLS,
  73                .init           = tegra30_spi_init,
  74                .claim_bus      = tegra30_spi_claim_bus,
  75                .cs_is_valid    = tegra30_spi_cs_is_valid,
  76                .setup_slave    = tegra30_spi_setup_slave,
  77                .free_slave     = tegra30_spi_free_slave,
  78                .cs_activate    = tegra30_spi_cs_activate,
  79                .cs_deactivate  = tegra30_spi_cs_deactivate,
  80                .xfer           = tegra30_spi_xfer,
  81        },
  82#endif
  83#ifdef CONFIG_TEGRA114_SPI
  84        {
  85                .compat         = COMPAT_NVIDIA_TEGRA114_SPI,
  86                .max_ctrls      = CONFIG_TEGRA114_SPI_CTRLS,
  87                .init           = tegra114_spi_init,
  88                .claim_bus      = tegra114_spi_claim_bus,
  89                .cs_is_valid    = tegra114_spi_cs_is_valid,
  90                .setup_slave    = tegra114_spi_setup_slave,
  91                .free_slave     = tegra114_spi_free_slave,
  92                .cs_activate    = tegra114_spi_cs_activate,
  93                .cs_deactivate  = tegra114_spi_cs_deactivate,
  94                .xfer           = tegra114_spi_xfer,
  95        },
  96#endif
  97};
  98
  99static struct fdt_spi_driver *driver;
 100
 101int spi_cs_is_valid(unsigned int bus, unsigned int cs)
 102{
 103        if (!driver)
 104                return 0;
 105        else if (!driver->cs_is_valid)
 106                return 1;
 107        else
 108                return driver->cs_is_valid(bus, cs);
 109}
 110
 111struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 112                unsigned int max_hz, unsigned int mode)
 113{
 114        if (!driver || !driver->setup_slave)
 115                return NULL;
 116
 117        return driver->setup_slave(bus, cs, max_hz, mode);
 118}
 119
 120void spi_free_slave(struct spi_slave *slave)
 121{
 122        if (driver && driver->free_slave)
 123                return driver->free_slave(slave);
 124}
 125
 126static int spi_init_driver(struct fdt_spi_driver *driver)
 127{
 128        int count;
 129        int node_list[driver->max_ctrls];
 130
 131        count = fdtdec_find_aliases_for_id(gd->fdt_blob, "spi",
 132                                           driver->compat,
 133                                           node_list,
 134                                           driver->max_ctrls);
 135        return driver->init(node_list, count);
 136}
 137
 138void spi_init(void)
 139{
 140        int i;
 141
 142        for (i = 0; i < ARRAY_SIZE(fdt_spi_drivers); i++) {
 143                driver = &fdt_spi_drivers[i];
 144                if (!spi_init_driver(driver))
 145                        break;
 146        }
 147        if (i == ARRAY_SIZE(fdt_spi_drivers))
 148                driver = NULL;
 149}
 150
 151int spi_claim_bus(struct spi_slave *slave)
 152{
 153        if (!driver)
 154                return 1;
 155        if (!driver->claim_bus)
 156                return 0;
 157
 158        return driver->claim_bus(slave);
 159}
 160
 161void spi_release_bus(struct spi_slave *slave)
 162{
 163        if (driver && driver->release_bus)
 164                driver->release_bus(slave);
 165}
 166
 167void spi_cs_activate(struct spi_slave *slave)
 168{
 169        if (driver && driver->cs_activate)
 170                driver->cs_activate(slave);
 171}
 172
 173void spi_cs_deactivate(struct spi_slave *slave)
 174{
 175        if (driver && driver->cs_deactivate)
 176                driver->cs_deactivate(slave);
 177}
 178
 179int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 180             const void *data_out, void *data_in, unsigned long flags)
 181{
 182        if (!driver || !driver->xfer)
 183                return -1;
 184
 185        return driver->xfer(slave, bitlen, data_out, data_in, flags);
 186}
 187