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/dev/ahci/ahci_fsl_fdt.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2020 Alstom Group
    5  * Copyright (c) 2020 Semihalf
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following 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 /* AHCI controller driver for NXP QorIQ Layerscape SoCs. */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD$");
   33 
   34 #include <sys/stdint.h>
   35 #include <sys/stddef.h>
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/kernel.h>
   39 #include <sys/bus.h>
   40 #include <sys/module.h>
   41 #include <sys/sysctl.h>
   42 #include <sys/rman.h>
   43 #include <sys/unistd.h>
   44 
   45 #include <machine/bus.h>
   46 #include <machine/resource.h>
   47 
   48 #include <dev/ofw/ofw_bus.h>
   49 #include <dev/ofw/ofw_bus_subr.h>
   50 
   51 #include <dev/ahci/ahci.h>
   52 
   53 #include <dev/extres/clk/clk.h>
   54 
   55 #define AHCI_FSL_REG_PHY1       0xa8
   56 #define AHCI_FSL_REG_PHY2       0xac
   57 #define AHCI_FSL_REG_PHY3       0xb0
   58 #define AHCI_FSL_REG_PHY4       0xb4
   59 #define AHCI_FSL_REG_PHY5       0xb8
   60 #define AHCI_FSL_REG_AXICC      0xbc
   61 #define AHCI_FSL_REG_PTC        0xc8
   62 
   63 #define AHCI_FSL_LS1021A_AXICC  0xc0
   64 
   65 #define AHCI_FSL_REG_PHY1_TTA_MASK      0x0001ffff
   66 #define AHCI_FSL_REG_PHY1_SNM           (1 << 17)
   67 #define AHCI_FSL_REG_PHY1_SNR           (1 << 18)
   68 #define AHCI_FSL_REG_PHY1_FPR           (1 << 20)
   69 #define AHCI_FSL_REG_PHY1_PBPS_LBP      0
   70 #define AHCI_FSL_REG_PHY1_PBPS_LFTP     (0x01 << 21)
   71 #define AHCI_FSL_REG_PHY1_PBPS_MFTP     (0x02 << 21)
   72 #define AHCI_FSL_REG_PHY1_PBPS_HFTP     (0x03 << 21)
   73 #define AHCI_FSL_REG_PHY1_PBPS_PRBS     (0x04 << 21)
   74 #define AHCI_FSL_REG_PHY1_PBPS_BIST     (0x05 << 21)
   75 #define AHCI_FSL_REG_PHY1_PBPE          (1 << 24)
   76 #define AHCI_FSL_REG_PHY1_PBCE          (1 << 25)
   77 #define AHCI_FSL_REG_PHY1_PBPNA         (1 << 26)
   78 #define AHCI_FSL_REG_PHY1_STB           (1 << 27)
   79 #define AHCI_FSL_REG_PHY1_PSSO          (1 << 28)
   80 #define AHCI_FSL_REG_PHY1_PSS           (1 << 29)
   81 #define AHCI_FSL_REG_PHY1_ERSN          (1 << 30)
   82 #define AHCI_FSL_REG_PHY1_ESDF          (1 << 31)
   83 
   84 #define AHCI_FSL_REG_PHY_MASK           0xff
   85 
   86 #define AHCI_FSL_PHY2_CIBGMN_SHIFT      0
   87 #define AHCI_FSL_PHY2_CIBGMX_SHIFT      8
   88 #define AHCI_FSL_PHY2_CIBGN_SHIFT       16
   89 #define AHCI_FSL_PHY2_CINMP_SHIFT       24
   90 
   91 
   92 #define AHCI_FSL_PHY3_CWBGMN_SHIFT      0
   93 #define AHCI_FSL_PHY3_CWBGMX_SHIFT      8
   94 #define AHCI_FSL_PHY3_CWBGN_SHIFT       16
   95 #define AHCI_FSL_PHY3_CWNMP_SHIFT       24
   96 
   97 /* Only in LS1021A */
   98 #define AHCI_FSL_PHY4_BMX_SHIFT         0
   99 #define AHCI_FSL_PHY4_BNM_SHIFT         8
  100 #define AHCI_FSL_PHY4_SFD_SHIFT         16
  101 #define AHCI_FSL_PHY4_PTST_SHIFT        24
  102 
  103 /* Only in LS1021A */
  104 #define AHCI_FSL_PHY5_RIT_SHIFT         0
  105 #define AHCI_FSL_PHY5_RCT_SHIFT         20
  106 
  107 #define AHCI_FSL_REG_PTC_RXWM_MASK      0x0000007f
  108 #define AHCI_FSL_REG_PTC_ENBD           (1 << 8)
  109 #define AHCI_FSL_REG_PTC_ITM            (1 << 9)
  110 
  111 #define AHCI_FSL_REG_PHY1_CFG                                           \
  112     ((0x1fffe & AHCI_FSL_REG_PHY1_TTA_MASK) |                           \
  113      AHCI_FSL_REG_PHY1_SNM | AHCI_FSL_REG_PHY1_PSS | AHCI_FSL_REG_PHY1_ESDF)
  114 
  115 #define AHCI_FSL_REG_PHY2_CFG                                           \
  116     ((0x1f << AHCI_FSL_PHY2_CIBGMN_SHIFT) |                             \
  117      (0x4d << AHCI_FSL_PHY2_CIBGMX_SHIFT) |                             \
  118      (0x18 << AHCI_FSL_PHY2_CIBGN_SHIFT) |                              \
  119      (0x28 << AHCI_FSL_PHY2_CINMP_SHIFT))
  120 
  121 #define AHCI_FSL_REG_PHY2_CFG_LS1021A                                   \
  122     ((0x14 << AHCI_FSL_PHY2_CIBGMN_SHIFT) |                             \
  123      (0x34 << AHCI_FSL_PHY2_CIBGMX_SHIFT) |                             \
  124      (0x18 << AHCI_FSL_PHY2_CIBGN_SHIFT) |                              \
  125      (0x28 << AHCI_FSL_PHY2_CINMP_SHIFT))
  126 
  127 #define AHCI_FSL_REG_PHY3_CFG                                           \
  128     ((0x09 << AHCI_FSL_PHY3_CWBGMN_SHIFT) |                             \
  129      (0x15 << AHCI_FSL_PHY3_CWBGMX_SHIFT) |                             \
  130      (0x08 << AHCI_FSL_PHY3_CWBGN_SHIFT) |                              \
  131      (0x0e << AHCI_FSL_PHY3_CWNMP_SHIFT))
  132 
  133 #define AHCI_FSL_REG_PHY3_CFG_LS1021A                                   \
  134     ((0x06 << AHCI_FSL_PHY3_CWBGMN_SHIFT) |                             \
  135      (0x0e << AHCI_FSL_PHY3_CWBGMX_SHIFT) |                             \
  136      (0x08 << AHCI_FSL_PHY3_CWBGN_SHIFT) |                              \
  137      (0x0e << AHCI_FSL_PHY3_CWNMP_SHIFT))
  138 
  139 #define AHCI_FSL_REG_PHY4_CFG_LS1021A                                   \
  140     ((0x0b << AHCI_FSL_PHY4_BMX_SHIFT) |                                \
  141      (0x08 << AHCI_FSL_PHY4_BNM_SHIFT) |                                \
  142      (0x4a << AHCI_FSL_PHY4_SFD_SHIFT) |                                \
  143      (0x06 << AHCI_FSL_PHY4_PTST_SHIFT))
  144 
  145 #define AHCI_FSL_REG_PHY5_CFG_LS1021A                                   \
  146     ((0x86470 << AHCI_FSL_PHY5_RIT_SHIFT) |                             \
  147      (0x2aa << AHCI_FSL_PHY5_RCT_SHIFT))
  148 
  149 /* Bit 27 enabled so value of reserved bits remains as in documentation. */
  150 #define AHCI_FSL_REG_PTC_CFG                                            \
  151     ((0x29 & AHCI_FSL_REG_PTC_RXWM_MASK) | (1 << 27))
  152 
  153 #define AHCI_FSL_REG_AXICC_CFG  0x3fffffff
  154 
  155 
  156 #define AHCI_FSL_REG_ECC        0x0
  157 #define AHCI_FSL_REG_ECC_LS1021A        0x00020000
  158 #define AHCI_FSL_REG_ECC_LS1043A        0x80000000
  159 #define AHCI_FSL_REG_ECC_LS1028A        0x40000000
  160 
  161 
  162 #define QORIQ_AHCI_LS1021A      1
  163 #define QORIQ_AHCI_LS1028A      2
  164 #define QORIQ_AHCI_LS1043A      3
  165 #define QORIQ_AHCI_LS2080A      4
  166 #define QORIQ_AHCI_LS1046A      5
  167 #define QORIQ_AHCI_LS1088A      6
  168 #define QORIQ_AHCI_LS2088A      7
  169 #define QORIQ_AHCI_LX2160A      8
  170 
  171 struct ahci_fsl_fdt_controller {
  172         struct ahci_controller  ctlr;   /* Must be the first field. */
  173         int                     soc_type;
  174         struct resource         *r_ecc;
  175         int                     r_ecc_rid;
  176 };
  177 
  178 static const struct ofw_compat_data ahci_fsl_fdt_compat_data[] = {
  179         {"fsl,ls1021a-ahci",    QORIQ_AHCI_LS1021A},
  180         {"fsl,ls1028a-ahci",    QORIQ_AHCI_LS1028A},
  181         {"fsl,ls1043a-ahci",    QORIQ_AHCI_LS1043A},
  182         {"fsl,ls2080a-ahci",    QORIQ_AHCI_LS2080A},
  183         {"fsl,ls1046a-ahci",    QORIQ_AHCI_LS1046A},
  184         {"fsl,ls1088a-ahci",    QORIQ_AHCI_LS1088A},
  185         {"fsl,ls2088a-ahci",    QORIQ_AHCI_LS2088A},
  186         {"fsl,lx2160a-ahci",    QORIQ_AHCI_LX2160A},
  187         {NULL,                  0}
  188 };
  189 
  190 static bool ecc_inited;
  191 
  192 static int
  193 ahci_fsl_fdt_ecc_init(struct ahci_fsl_fdt_controller *ctrl)
  194 {
  195         uint32_t val;
  196 
  197         switch (ctrl->soc_type) {
  198         case QORIQ_AHCI_LS2080A:
  199         case QORIQ_AHCI_LS2088A:
  200                 return (0);
  201 
  202         case QORIQ_AHCI_LS1021A:
  203                 if (!ecc_inited && ctrl->r_ecc == NULL)
  204                         return (ENXIO);
  205                 if (!ecc_inited)
  206                         ATA_OUTL(ctrl->r_ecc, AHCI_FSL_REG_ECC,
  207                              AHCI_FSL_REG_ECC_LS1021A);
  208                 break;
  209 
  210         case QORIQ_AHCI_LS1043A:
  211         case QORIQ_AHCI_LS1046A:
  212                 if (!ecc_inited && ctrl->r_ecc == NULL)
  213                         return (ENXIO);
  214                 if (!ecc_inited) {
  215                         val = ATA_INL(ctrl->r_ecc, AHCI_FSL_REG_ECC);
  216                         val = AHCI_FSL_REG_ECC_LS1043A;
  217                         ATA_OUTL(ctrl->r_ecc, AHCI_FSL_REG_ECC, val);
  218                 }
  219                 break;
  220 
  221         case QORIQ_AHCI_LS1028A:
  222         case QORIQ_AHCI_LS1088A:
  223         case QORIQ_AHCI_LX2160A:
  224                 if (!ecc_inited && ctrl->r_ecc == NULL)
  225                         return (ENXIO);
  226                 if (!ecc_inited) {
  227 
  228                         val = ATA_INL(ctrl->r_ecc, AHCI_FSL_REG_ECC);
  229                         val |= AHCI_FSL_REG_ECC_LS1028A;
  230                         ATA_OUTL(ctrl->r_ecc, AHCI_FSL_REG_ECC, val);
  231                 }
  232                 break;
  233 
  234         default:
  235                 panic("Unimplemented SOC type: %d", ctrl->soc_type);
  236         }
  237 
  238         ecc_inited = true;
  239         return (0);
  240 }
  241 
  242 static void
  243 ahci_fsl_fdt_phy_init(struct ahci_fsl_fdt_controller *ctrl)
  244 {
  245         struct ahci_controller *ahci;
  246 
  247         ahci = &ctrl->ctlr;
  248         if (ctrl->soc_type == QORIQ_AHCI_LS1021A) {
  249                 ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_PHY1,
  250                     AHCI_FSL_REG_PHY1_CFG);
  251                 ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_PHY2,
  252                     AHCI_FSL_REG_PHY2_CFG_LS1021A);
  253                 ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_PHY3,
  254                     AHCI_FSL_REG_PHY3_CFG_LS1021A);
  255                 ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_PHY4,
  256                     AHCI_FSL_REG_PHY4_CFG_LS1021A);
  257                 ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_PHY5,
  258                     AHCI_FSL_REG_PHY5_CFG_LS1021A);
  259                 ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_PTC,
  260                     AHCI_FSL_REG_PTC_CFG);
  261 
  262                 if (ctrl->ctlr.dma_coherent)
  263                         ATA_OUTL(ahci->r_mem, AHCI_FSL_LS1021A_AXICC,
  264                             AHCI_FSL_REG_AXICC_CFG);
  265         } else {
  266                 ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_PHY1,
  267                     AHCI_FSL_REG_PHY1_CFG);
  268                 ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_PHY2,
  269                     AHCI_FSL_REG_PHY2_CFG);
  270                 ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_PHY3,
  271                     AHCI_FSL_REG_PHY3_CFG);
  272                 ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_PTC,
  273                     AHCI_FSL_REG_PTC_CFG);
  274 
  275                 if (ctrl->ctlr.dma_coherent)
  276                         ATA_OUTL(ahci->r_mem, AHCI_FSL_REG_AXICC,
  277                             AHCI_FSL_REG_AXICC_CFG);
  278         }
  279 }
  280 
  281 static int
  282 ahci_fsl_fdt_probe(device_t dev)
  283 {
  284         if (!ofw_bus_status_okay(dev))
  285                 return (ENXIO);
  286 
  287         if (!ofw_bus_search_compatible(dev, ahci_fsl_fdt_compat_data)->ocd_data)
  288                 return (ENXIO);
  289 
  290         device_set_desc(dev, "NXP QorIQ Layerscape AHCI controller");
  291         return (BUS_PROBE_DEFAULT);
  292 }
  293 
  294 static int
  295 ahci_fsl_fdt_attach(device_t dev)
  296 {
  297         struct ahci_fsl_fdt_controller *ctlr;
  298         struct ahci_controller *ahci;
  299         phandle_t node;
  300         clk_t clock;
  301         int ret;
  302 
  303         node = ofw_bus_get_node(dev);
  304         ctlr = device_get_softc(dev);
  305         ctlr->soc_type =
  306             ofw_bus_search_compatible(dev, ahci_fsl_fdt_compat_data)->ocd_data;
  307         ahci = &ctlr->ctlr;
  308         ahci->dev = dev;
  309         ahci->r_rid = 0;
  310         ahci->quirks = AHCI_Q_NOPMP;
  311 
  312         ahci->dma_coherent = OF_hasprop(node, "dma-coherent");
  313 
  314         ret = clk_get_by_ofw_index(dev, node, 0, &clock);
  315         if (ret != 0) {
  316                 device_printf(dev, "No clock found.\n");
  317                 return (ENXIO);
  318         }
  319 
  320         ret = clk_enable(clock);
  321         if (ret !=0) {
  322                 device_printf(dev, "Could not enable clock.\n");
  323                 return (ENXIO);
  324         }
  325 
  326         if (OF_hasprop(node, "reg-names") && ofw_bus_find_string_index(node,
  327             "reg-names", "ahci", &ahci->r_rid)) {
  328                 device_printf(dev, "Could not locate 'ahci' string in the "
  329                     "'reg-names' property");
  330                 return (ENOENT);
  331         }
  332 
  333         ahci->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  334             &ahci->r_rid, RF_ACTIVE);
  335         if (!ahci->r_mem) {
  336                 device_printf(dev,
  337                     "Could not allocate resources for controller\n");
  338                 return (ENOMEM);
  339         }
  340 
  341         ret = ofw_bus_find_string_index(node, "reg-names", "sata-ecc",
  342             &ctlr->r_ecc_rid);
  343         if (ret == 0) {
  344                 ctlr->r_ecc = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  345                     &ctlr->r_ecc_rid, RF_ACTIVE| RF_SHAREABLE);
  346                 if (!ctlr->r_ecc) {
  347                         device_printf(dev,
  348                             "Could not allocate resources for controller\n");
  349                         ret = ENOMEM;
  350                         goto err_free_mem;
  351                 }
  352         } else if (ret != ENOENT) {
  353                 device_printf(dev, "Could not locate 'sata-ecc' string in "
  354                 "the 'reg-names' property");
  355                 goto err_free_mem;
  356         }
  357 
  358         ret = ahci_fsl_fdt_ecc_init(ctlr);
  359         if (ret != 0) {
  360                 device_printf(dev, "Could not initialize 'ecc' registers");
  361                 goto err_free_mem;
  362         }
  363 
  364         /* Setup controller defaults. */
  365         ahci->numirqs = 1;
  366         ahci_fsl_fdt_phy_init(ctlr);
  367 
  368         /* Reset controller. */
  369         ret = ahci_ctlr_reset(dev);
  370         if (ret)
  371                 goto err_free_mem;
  372 
  373         ret = ahci_attach(dev);
  374         if (ret) {
  375                 device_printf(dev,
  376                     "Could not initialize AHCI, with error: %d\n", ret);
  377                 goto err_free_ecc;
  378         }
  379         return (0);
  380 
  381 err_free_mem:
  382         bus_free_resource(dev, SYS_RES_MEMORY, ahci->r_mem);
  383 err_free_ecc:
  384         if (ctlr->r_ecc)
  385                 bus_free_resource(dev, SYS_RES_MEMORY, ctlr->r_ecc);
  386         return (ret);
  387 }
  388 
  389 static int
  390 ahci_fsl_fdt_detach(device_t dev)
  391 {
  392         struct ahci_fsl_fdt_controller *ctlr;
  393 
  394         ctlr = device_get_softc(dev);
  395         if (ctlr->r_ecc)
  396                 bus_free_resource(dev, SYS_RES_MEMORY, ctlr->r_ecc);
  397         return ahci_detach(dev);
  398 }
  399 
  400 static const device_method_t ahci_fsl_fdt_methods[] = {
  401         DEVMETHOD(device_probe,                 ahci_fsl_fdt_probe),
  402         DEVMETHOD(device_attach,                ahci_fsl_fdt_attach),
  403         DEVMETHOD(device_detach,                ahci_fsl_fdt_detach),
  404         DEVMETHOD(bus_alloc_resource,           ahci_alloc_resource),
  405         DEVMETHOD(bus_release_resource,         ahci_release_resource),
  406         DEVMETHOD(bus_setup_intr,               ahci_setup_intr),
  407         DEVMETHOD(bus_teardown_intr,            ahci_teardown_intr),
  408         DEVMETHOD(bus_print_child,              ahci_print_child),
  409         DEVMETHOD(bus_child_location,           ahci_child_location),
  410         DEVMETHOD(bus_get_dma_tag,              ahci_get_dma_tag),
  411         DEVMETHOD_END
  412 };
  413 
  414 static driver_t ahci_fsl_fdt_driver = {
  415         "ahci",
  416         ahci_fsl_fdt_methods,
  417         sizeof(struct ahci_fsl_fdt_controller),
  418 };
  419 
  420 DRIVER_MODULE(ahci_fsl, simplebus, ahci_fsl_fdt_driver, NULL, NULL);
  421 DRIVER_MODULE(ahci_fsl, ofwbus, ahci_fsl_fdt_driver, NULL, NULL);

Cache object: 35e3bcba9d1c5e7bb718f0df208485e4


[ 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.