The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/mips/atheros/ar531x/ar5315_spi.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2016, Hiroki Mori
    3  * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice unmodified, this list of conditions, and the following
   11  *    disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 
   35 #include <sys/bus.h>
   36 #include <sys/interrupt.h>
   37 #include <sys/malloc.h>
   38 #include <sys/kernel.h>
   39 #include <sys/module.h>
   40 #include <sys/rman.h>
   41 #include <sys/sysctl.h>
   42 
   43 #include <vm/vm.h>
   44 #include <vm/pmap.h>
   45 #include <vm/vm_extern.h>
   46 
   47 #include <machine/bus.h>
   48 #include <machine/cpu.h>
   49 #include <machine/pmap.h>
   50 
   51 #include <dev/spibus/spi.h>
   52 #include <dev/spibus/spibusvar.h>
   53 #include "spibus_if.h"
   54 
   55 #include <mips/atheros/ar531x/arspireg.h>
   56 #include <mips/atheros/ar531x/ar5315reg.h>
   57 
   58 #undef AR531X_SPI_DEBUG
   59 #ifdef AR531X_SPI_DEBUG
   60 #define dprintf printf
   61 #else
   62 #define dprintf(x, arg...)
   63 #endif
   64 
   65 /*
   66  * register space access macros
   67  */
   68 #define SPI_WRITE(sc, reg, val) do {    \
   69                 bus_write_4(sc->sc_mem_res, (reg), (val)); \
   70         } while (0)
   71 
   72 #define SPI_READ(sc, reg)        bus_read_4(sc->sc_mem_res, (reg))
   73 
   74 #define SPI_SET_BITS(sc, reg, bits)     \
   75         SPI_WRITE(sc, reg, SPI_READ(sc, (reg)) | (bits))
   76 
   77 #define SPI_CLEAR_BITS(sc, reg, bits)   \
   78         SPI_WRITE(sc, reg, SPI_READ(sc, (reg)) & ~(bits))
   79 
   80 struct ar5315_spi_softc {
   81         device_t                sc_dev;
   82         struct resource         *sc_mem_res;
   83         uint32_t                sc_reg_ctrl;
   84         uint32_t                sc_debug;
   85 };
   86 
   87 static void
   88 ar5315_spi_attach_sysctl(device_t dev)
   89 {
   90         struct ar5315_spi_softc *sc;
   91         struct sysctl_ctx_list *ctx;
   92         struct sysctl_oid *tree;
   93 
   94         sc = device_get_softc(dev);
   95         ctx = device_get_sysctl_ctx(dev);
   96         tree = device_get_sysctl_tree(dev);
   97 
   98         SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
   99                 "debug", CTLFLAG_RW, &sc->sc_debug, 0,
  100                 "ar5315_spi debugging flags");
  101 }
  102 
  103 static int
  104 ar5315_spi_probe(device_t dev)
  105 {
  106         device_set_desc(dev, "AR5315 SPI");
  107         return (0);
  108 }
  109 
  110 static int
  111 ar5315_spi_attach(device_t dev)
  112 {
  113         struct ar5315_spi_softc *sc = device_get_softc(dev);
  114         int rid;
  115 
  116         sc->sc_dev = dev;
  117         rid = 0;
  118         sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 
  119             RF_ACTIVE);
  120         if (!sc->sc_mem_res) {
  121                 device_printf(dev, "Could not map memory\n");
  122                 return (ENXIO);
  123         }
  124 
  125         device_add_child(dev, "spibus", -1);
  126         ar5315_spi_attach_sysctl(dev);
  127 
  128         return (bus_generic_attach(dev));
  129 }
  130 
  131 static void
  132 ar5315_spi_chip_activate(struct ar5315_spi_softc *sc, int cs)
  133 {
  134 }
  135 
  136 static void
  137 ar5315_spi_chip_deactivate(struct ar5315_spi_softc *sc, int cs)
  138 {
  139 }
  140 
  141 static int
  142 ar5315_spi_get_block(off_t offset, caddr_t data, off_t count)
  143 {
  144         int i;
  145         for(i = 0; i < count / 4; ++i) {
  146                 *((uint32_t *)data + i) = ATH_READ_REG(AR5315_MEM1_BASE + offset + i * 4);
  147         }
  148 //      printf("ar5315_spi_get_blockr: %x %x %x\n", 
  149 //              (int)offset, (int)count, *(uint32_t *)data);
  150         return (0);
  151 }
  152 
  153 static int
  154 ar5315_spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
  155 {
  156         struct ar5315_spi_softc *sc;
  157         uint8_t *buf_in, *buf_out;
  158         int lin, lout;
  159         uint32_t ctl, cnt, op, rdat, cs;
  160         int i, j;
  161 
  162         sc = device_get_softc(dev);
  163 
  164         if (sc->sc_debug & 0x8000)
  165                 printf("ar5315_spi_transfer: CMD ");
  166 
  167         spibus_get_cs(child, &cs);
  168 
  169         cs &= ~SPIBUS_CS_HIGH;
  170 
  171         /* Open SPI controller interface */
  172         ar5315_spi_chip_activate(sc, cs);
  173 
  174         do {
  175                 ctl = SPI_READ(sc, ARSPI_REG_CTL);
  176         } while (ctl & ARSPI_CTL_BUSY);
  177 
  178         /*
  179          * Transfer command
  180          */
  181         buf_out = (uint8_t *)cmd->tx_cmd;
  182         op = buf_out[0];
  183         if(op == 0x0b) {
  184                 int offset = buf_out[1] << 16 | buf_out[2] << 8 | buf_out[3];
  185                 ar5315_spi_get_block(offset, cmd->rx_data, cmd->rx_data_sz);
  186                 return (0);
  187         }
  188         do {
  189                 ctl = SPI_READ(sc, ARSPI_REG_CTL);
  190         } while (ctl & ARSPI_CTL_BUSY);
  191         if (sc->sc_debug & 0x8000) {
  192                 printf("%08x ", op);
  193                 printf("tx_cmd_sz=%d rx_cmd_sz=%d ", cmd->tx_cmd_sz,
  194                         cmd->rx_cmd_sz);
  195                 if(cmd->tx_cmd_sz != 1) {
  196                         printf("%08x ", *((uint32_t *)cmd->tx_cmd));
  197                         printf("%08x ", *((uint32_t *)cmd->tx_cmd + 1));
  198                 }
  199         }
  200         SPI_WRITE(sc, ARSPI_REG_OPCODE, op);
  201 
  202         /* clear all of the tx and rx bits */
  203         ctl &= ~(ARSPI_CTL_TXCNT_MASK | ARSPI_CTL_RXCNT_MASK);
  204 
  205         /* now set txcnt */
  206         cnt = 1;
  207 
  208         ctl |= (cnt << ARSPI_CTL_TXCNT_SHIFT);
  209 
  210         cnt = 24;
  211         /* now set txcnt */
  212         if(cmd->rx_cmd_sz < 24)
  213                 cnt = cmd->rx_cmd_sz;
  214         ctl |= (cnt << ARSPI_CTL_RXCNT_SHIFT);
  215 
  216         ctl |= ARSPI_CTL_START;
  217 
  218         SPI_WRITE(sc, ARSPI_REG_CTL, ctl);
  219 
  220         if(op == 0x0b)
  221                 SPI_WRITE(sc, ARSPI_REG_DATA, 0);
  222         if (sc->sc_debug & 0x8000)
  223                 printf("\nDATA ");
  224         /*
  225          * Receive/transmit data (depends on  command)
  226          */
  227 //      buf_out = (uint8_t *)cmd->tx_data;
  228         buf_in = (uint8_t *)cmd->rx_cmd;
  229 //      lout = cmd->tx_data_sz;
  230         lin = cmd->rx_cmd_sz;
  231         if (sc->sc_debug & 0x8000)
  232                 printf("t%d r%d ", lout, lin);
  233         for(i = 0; i <= (cnt - 1) / 4; ++i) {
  234                 do {
  235                         ctl = SPI_READ(sc, ARSPI_REG_CTL);
  236                 } while (ctl & ARSPI_CTL_BUSY);
  237 
  238                 rdat = SPI_READ(sc, ARSPI_REG_DATA);
  239                 if (sc->sc_debug & 0x8000)
  240                         printf("I%08x ", rdat);
  241 
  242                 for(j = 0; j < 4; ++j) {
  243                         buf_in[i * 4 + j + 1] = 0xff & (rdat >> (8 * j));
  244                         if(i * 4 + j  + 2 == cnt)
  245                                 break;
  246                 }
  247         }
  248 
  249         ar5315_spi_chip_deactivate(sc, cs);
  250         /*
  251          * Close SPI controller interface, restore flash memory mapped access.
  252          */
  253         if (sc->sc_debug & 0x8000)
  254                 printf("\n");
  255 
  256         return (0);
  257 }
  258 
  259 static int
  260 ar5315_spi_detach(device_t dev)
  261 {
  262         struct ar5315_spi_softc *sc = device_get_softc(dev);
  263 
  264         if (sc->sc_mem_res)
  265                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
  266 
  267         return (0);
  268 }
  269 
  270 static device_method_t ar5315_spi_methods[] = {
  271         /* Device interface */
  272         DEVMETHOD(device_probe,         ar5315_spi_probe),
  273         DEVMETHOD(device_attach,        ar5315_spi_attach),
  274         DEVMETHOD(device_detach,        ar5315_spi_detach),
  275 
  276         DEVMETHOD(spibus_transfer,      ar5315_spi_transfer),
  277 //      DEVMETHOD(spibus_get_block,     ar5315_spi_get_block),
  278 
  279         DEVMETHOD_END
  280 };
  281 
  282 static driver_t ar5315_spi_driver = {
  283         "spi",
  284         ar5315_spi_methods,
  285         sizeof(struct ar5315_spi_softc),
  286 };
  287 
  288 static devclass_t ar5315_spi_devclass;
  289 
  290 DRIVER_MODULE(ar5315_spi, nexus, ar5315_spi_driver, ar5315_spi_devclass, 0, 0);

Cache object: 73becd5dce77c17740eac623d31a9e03


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.