1 /* $OpenBSD: octsctl.c,v 1.2 2019/01/12 13:50:52 visa Exp $ */ 2 3 /* 4 * Copyright (c) 2017 Visa Hankala 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* 20 * Driver for OCTEON SATA controller bridge. 21 */ 22 23 #include <sys/param.h> 24 #include <sys/systm.h> 25 #include <sys/device.h> 26 27 #include <machine/bus.h> 28 #include <machine/fdt.h> 29 30 #include <dev/ofw/fdt.h> 31 #include <dev/ofw/openfirm.h> 32 33 #define SCTL_SHIM_CFG 0xe8 34 #define SCTL_SHIM_CFG_READ_CMD 0x0000000000001000ul 35 #define SCTL_SHIM_CFG_DMA_BYTE_SWAP 0x0000000000000300ul 36 #define SCTL_SHIM_CFG_DMA_BYTE_SWAP_SHIFT 8 37 #define SCTL_SHIM_CFG_CSR_BYTE_SWAP 0x0000000000000003ul 38 #define SCTL_SHIM_CFG_CSR_BYTE_SWAP_SHIFT 0 39 40 struct octsctl_softc { 41 struct device sc_dev; 42 bus_space_tag_t sc_iot; 43 bus_space_handle_t sc_ioh; 44 }; 45 46 int octsctl_match(struct device *, void *, void *); 47 void octsctl_attach(struct device *, struct device *, void *); 48 49 const struct cfattach octsctl_ca = { 50 sizeof(struct octsctl_softc), octsctl_match, octsctl_attach 51 }; 52 53 struct cfdriver octsctl_cd = { 54 NULL, "octsctl", DV_DULL 55 }; 56 57 int 58 octsctl_match(struct device *parent, void *match, void *aux) 59 { 60 struct fdt_attach_args *faa = aux; 61 62 return OF_is_compatible(faa->fa_node, "cavium,octeon-7130-sata-uctl"); 63 } 64 65 void 66 octsctl_attach(struct device *parent, struct device *self, void *aux) 67 { 68 struct fdt_reg child_reg; 69 struct fdt_attach_args child_faa; 70 struct fdt_attach_args *faa = aux; 71 struct octsctl_softc *sc = (struct octsctl_softc *)self; 72 uint64_t val; 73 uint32_t reg[4]; 74 int child; 75 76 child = OF_child(faa->fa_node); 77 78 /* 79 * On some machines, the bridge controller node does not have 80 * an AHCI controller node as a child. 81 */ 82 if (child == 0) { 83 printf(": disabled\n"); 84 return; 85 } 86 87 if (faa->fa_nreg != 1) { 88 printf(": expected one IO space, got %d\n", faa->fa_nreg); 89 return; 90 } 91 92 if (OF_getpropint(faa->fa_node, "#address-cells", 0) != 2 || 93 OF_getpropint(faa->fa_node, "#size-cells", 0) != 2) { 94 printf(": invalid fdt reg cells\n"); 95 return; 96 } 97 if (OF_getproplen(child, "reg") != sizeof(reg)) { 98 printf(": invalid child fdt reg\n"); 99 return; 100 } 101 OF_getpropintarray(child, "reg", reg, sizeof(reg)); 102 child_reg.addr = ((uint64_t)reg[0] << 32) | reg[1]; 103 child_reg.size = ((uint64_t)reg[2] << 32) | reg[3]; 104 105 sc->sc_iot = faa->fa_iot; 106 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, faa->fa_reg[0].size, 107 0, &sc->sc_ioh)) { 108 printf(": could not map registers\n"); 109 goto error; 110 } 111 112 val = bus_space_read_8(sc->sc_iot, sc->sc_ioh, SCTL_SHIM_CFG); 113 val &= ~SCTL_SHIM_CFG_CSR_BYTE_SWAP; 114 val &= ~SCTL_SHIM_CFG_DMA_BYTE_SWAP; 115 val |= 3ul << SCTL_SHIM_CFG_CSR_BYTE_SWAP_SHIFT; 116 val |= 1ul << SCTL_SHIM_CFG_DMA_BYTE_SWAP_SHIFT; 117 val |= SCTL_SHIM_CFG_READ_CMD; 118 bus_space_write_8(sc->sc_iot, sc->sc_ioh, SCTL_SHIM_CFG, val); 119 (void)bus_space_read_8(sc->sc_iot, sc->sc_ioh, SCTL_SHIM_CFG); 120 121 printf("\n"); 122 123 memset(&child_faa, 0, sizeof(child_faa)); 124 child_faa.fa_name = ""; 125 child_faa.fa_node = child; 126 child_faa.fa_iot = faa->fa_iot; 127 child_faa.fa_dmat = faa->fa_dmat; 128 child_faa.fa_reg = &child_reg; 129 child_faa.fa_nreg = 1; 130 /* child_faa.fa_intr is not utilized. */ 131 132 config_found(self, &child_faa, NULL); 133 134 return; 135 136 error: 137 if (sc->sc_ioh != 0) 138 bus_space_unmap(sc->sc_iot, sc->sc_ioh, faa->fa_reg[0].size); 139 } 140