15f55eefbSWojciech Macek /* 25f55eefbSWojciech Macek * Copyright (c) 2017 Semihalf. 35f55eefbSWojciech Macek * Copyright (c) 2017 Stormshield. 45f55eefbSWojciech Macek * All rights reserved. 55f55eefbSWojciech Macek * 65f55eefbSWojciech Macek * Redistribution and use in source and binary forms, with or without 75f55eefbSWojciech Macek * modification, are permitted provided that the following conditions 85f55eefbSWojciech Macek * are met: 95f55eefbSWojciech Macek * 1. Redistributions of source code must retain the above copyright 105f55eefbSWojciech Macek * notice, this list of conditions and the following disclaimer. 115f55eefbSWojciech Macek * 2. Redistributions in binary form must reproduce the above copyright 125f55eefbSWojciech Macek * notice, this list of conditions and the following disclaimer in the 135f55eefbSWojciech Macek * documentation and/or other materials provided with the distribution. 145f55eefbSWojciech Macek * 155f55eefbSWojciech Macek * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 165f55eefbSWojciech Macek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 175f55eefbSWojciech Macek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 185f55eefbSWojciech Macek * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 195f55eefbSWojciech Macek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 205f55eefbSWojciech Macek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 215f55eefbSWojciech Macek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 225f55eefbSWojciech Macek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 235f55eefbSWojciech Macek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 245f55eefbSWojciech Macek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 255f55eefbSWojciech Macek * SUCH DAMAGE. 265f55eefbSWojciech Macek */ 275f55eefbSWojciech Macek 285f55eefbSWojciech Macek #include <sys/cdefs.h> 295f55eefbSWojciech Macek __FBSDID("$FreeBSD$"); 305f55eefbSWojciech Macek 315f55eefbSWojciech Macek #include <sys/stdint.h> 325f55eefbSWojciech Macek #include <sys/stddef.h> 335f55eefbSWojciech Macek #include <sys/param.h> 345f55eefbSWojciech Macek #include <sys/systm.h> 355f55eefbSWojciech Macek #include <sys/kernel.h> 365f55eefbSWojciech Macek #include <sys/bus.h> 375f55eefbSWojciech Macek #include <sys/module.h> 385f55eefbSWojciech Macek #include <sys/sysctl.h> 395f55eefbSWojciech Macek #include <sys/rman.h> 405f55eefbSWojciech Macek #include <sys/unistd.h> 415f55eefbSWojciech Macek 425f55eefbSWojciech Macek #include <machine/bus.h> 435f55eefbSWojciech Macek #include <machine/resource.h> 445f55eefbSWojciech Macek 455f55eefbSWojciech Macek #include <dev/ofw/ofw_bus.h> 465f55eefbSWojciech Macek #include <dev/ofw/ofw_bus_subr.h> 475f55eefbSWojciech Macek 485f55eefbSWojciech Macek #include <dev/ahci/ahci.h> 495f55eefbSWojciech Macek 505f55eefbSWojciech Macek #define AHCI_VENDOR_SPECIFIC_0_ADDR 0xa0 515f55eefbSWojciech Macek #define AHCI_VENDOR_SPECIFIC_0_DATA 0xa4 525f55eefbSWojciech Macek 535f55eefbSWojciech Macek #define AHCI_HC_DEVSTR "Marvell AHCI Controller" 545f55eefbSWojciech Macek #define AHCI_HC_VENDOR "Marvell" 555f55eefbSWojciech Macek 565f55eefbSWojciech Macek static device_attach_t ahci_mv_fdt_attach; 575f55eefbSWojciech Macek 585f55eefbSWojciech Macek static struct ofw_compat_data compatible_data[] = { 595f55eefbSWojciech Macek {"marvell,armada-380-ahci", true}, 605f55eefbSWojciech Macek {NULL, false} 615f55eefbSWojciech Macek }; 625f55eefbSWojciech Macek 635f55eefbSWojciech Macek static void 645f55eefbSWojciech Macek ahci_mv_regret_config(struct ahci_controller *ctlr) 655f55eefbSWojciech Macek { 665f55eefbSWojciech Macek 675f55eefbSWojciech Macek /* 685f55eefbSWojciech Macek * Enable the regret bit to allow the SATA unit to regret 695f55eefbSWojciech Macek * a request that didn't receive an acknowledge 705f55eefbSWojciech Macek * and a avoid deadlock 715f55eefbSWojciech Macek */ 725f55eefbSWojciech Macek ATA_OUTL(ctlr->r_mem, AHCI_VENDOR_SPECIFIC_0_ADDR, 0x4); 735f55eefbSWojciech Macek ATA_OUTL(ctlr->r_mem, AHCI_VENDOR_SPECIFIC_0_DATA, 0x80); 745f55eefbSWojciech Macek } 755f55eefbSWojciech Macek 765f55eefbSWojciech Macek static int 775f55eefbSWojciech Macek ahci_mv_fdt_probe(device_t dev) 785f55eefbSWojciech Macek { 795f55eefbSWojciech Macek 805f55eefbSWojciech Macek if (!ofw_bus_status_okay(dev)) 815f55eefbSWojciech Macek return (ENXIO); 825f55eefbSWojciech Macek 835f55eefbSWojciech Macek if (!ofw_bus_search_compatible(dev, compatible_data)->ocd_data) 845f55eefbSWojciech Macek return (ENXIO); 855f55eefbSWojciech Macek 865f55eefbSWojciech Macek device_set_desc(dev, AHCI_HC_DEVSTR); 875f55eefbSWojciech Macek 885f55eefbSWojciech Macek return (BUS_PROBE_DEFAULT); 895f55eefbSWojciech Macek } 905f55eefbSWojciech Macek 915f55eefbSWojciech Macek static int 925f55eefbSWojciech Macek ahci_mv_fdt_attach(device_t dev) 935f55eefbSWojciech Macek { 945f55eefbSWojciech Macek struct ahci_controller *ctlr; 955f55eefbSWojciech Macek int rc; 965f55eefbSWojciech Macek 975f55eefbSWojciech Macek ctlr = device_get_softc(dev); 985f55eefbSWojciech Macek ctlr->dev = dev; 995f55eefbSWojciech Macek ctlr->r_rid = 0; 1005f55eefbSWojciech Macek ctlr->quirks = AHCI_Q_2CH; 1015f55eefbSWojciech Macek ctlr->numirqs = 1; 1025f55eefbSWojciech Macek 1035f55eefbSWojciech Macek if (ofw_bus_is_compatible(dev, "marvell,armada-380-ahci")) 1045f55eefbSWojciech Macek ctlr->quirks |= AHCI_Q_MRVL_SR_DEL; 1055f55eefbSWojciech Macek 1065f55eefbSWojciech Macek /* Allocate memory for controller */ 1075f55eefbSWojciech Macek ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 1085f55eefbSWojciech Macek &ctlr->r_rid, RF_ACTIVE | RF_SHAREABLE); 1095f55eefbSWojciech Macek if (ctlr->r_mem == NULL) { 1105f55eefbSWojciech Macek device_printf(dev, "Failed to alloc memory for controller\n"); 1115f55eefbSWojciech Macek return (ENOMEM); 1125f55eefbSWojciech Macek } 1135f55eefbSWojciech Macek 1145f55eefbSWojciech Macek /* Reset controller */ 1155f55eefbSWojciech Macek rc = ahci_ctlr_reset(dev); 1165f55eefbSWojciech Macek if (rc != 0) { 1175f55eefbSWojciech Macek device_printf(dev, "Failed to reset controller\n"); 1185f55eefbSWojciech Macek bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); 1195f55eefbSWojciech Macek return (ENXIO); 1205f55eefbSWojciech Macek } 1215f55eefbSWojciech Macek 1225f55eefbSWojciech Macek ahci_mv_regret_config(ctlr); 1235f55eefbSWojciech Macek 1245f55eefbSWojciech Macek rc = ahci_attach(dev); 1255f55eefbSWojciech Macek if (rc != 0) { 1265f55eefbSWojciech Macek device_printf(dev, "Failed to initialize AHCI, with error %d\n", rc); 1275f55eefbSWojciech Macek return (ENXIO); 1285f55eefbSWojciech Macek } 1295f55eefbSWojciech Macek 1305f55eefbSWojciech Macek return (0); 1315f55eefbSWojciech Macek } 1325f55eefbSWojciech Macek 1335f55eefbSWojciech Macek static device_method_t ahci_methods[] = { 1345f55eefbSWojciech Macek /* Device interface */ 1355f55eefbSWojciech Macek DEVMETHOD(device_probe, ahci_mv_fdt_probe), 1365f55eefbSWojciech Macek DEVMETHOD(device_attach, ahci_mv_fdt_attach), 1375f55eefbSWojciech Macek DEVMETHOD(device_detach, ahci_detach), 1385f55eefbSWojciech Macek DEVMETHOD(bus_alloc_resource, ahci_alloc_resource), 1395f55eefbSWojciech Macek DEVMETHOD(bus_release_resource, ahci_release_resource), 1405f55eefbSWojciech Macek DEVMETHOD(bus_setup_intr, ahci_setup_intr), 1415f55eefbSWojciech Macek DEVMETHOD(bus_teardown_intr, ahci_teardown_intr), 1425f55eefbSWojciech Macek DEVMETHOD(bus_print_child, ahci_print_child), 143ddfc9c4cSWarner Losh DEVMETHOD(bus_child_location, ahci_child_location), 1445f55eefbSWojciech Macek DEVMETHOD(bus_get_dma_tag, ahci_get_dma_tag), 1455f55eefbSWojciech Macek DEVMETHOD_END 1465f55eefbSWojciech Macek }; 1475f55eefbSWojciech Macek 1485f55eefbSWojciech Macek static driver_t ahci_driver = { 1495f55eefbSWojciech Macek "ahci", 1505f55eefbSWojciech Macek ahci_methods, 1515f55eefbSWojciech Macek sizeof(struct ahci_controller) 1525f55eefbSWojciech Macek }; 1535f55eefbSWojciech Macek 15423802d41SJohn Baldwin DRIVER_MODULE(ahci_mv, simplebus, ahci_driver, NULL, NULL); 15523802d41SJohn Baldwin DRIVER_MODULE(ahci_mv, ofwbus, ahci_driver, NULL, NULL); 156