1 /* $OpenBSD: octsctl.c,v 1.1 2017/07/28 14:54:13 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 /* 63 * On some machines, the bridge controller node does not have 64 * an AHCI controller node as a child. 65 */ 66 67 return OF_is_compatible(faa->fa_node, "cavium,octeon-7130-sata-uctl") && 68 OF_child(faa->fa_node) != 0; 69 } 70 71 void 72 octsctl_attach(struct device *parent, struct device *self, void *aux) 73 { 74 struct fdt_reg child_reg; 75 struct fdt_attach_args child_faa; 76 struct fdt_attach_args *faa = aux; 77 struct octsctl_softc *sc = (struct octsctl_softc *)self; 78 uint64_t val; 79 uint32_t reg[4]; 80 int child; 81 82 if (faa->fa_nreg != 1) { 83 printf(": expected one IO space, got %d\n", faa->fa_nreg); 84 return; 85 } 86 87 child = OF_child(faa->fa_node); 88 if (OF_getpropint(faa->fa_node, "#address-cells", 0) != 2 || 89 OF_getpropint(faa->fa_node, "#size-cells", 0) != 2) { 90 printf(": invalid fdt reg cells\n"); 91 return; 92 } 93 if (OF_getproplen(child, "reg") != sizeof(reg)) { 94 printf(": invalid child fdt reg\n"); 95 return; 96 } 97 OF_getpropintarray(child, "reg", reg, sizeof(reg)); 98 child_reg.addr = ((uint64_t)reg[0] << 32) | reg[1]; 99 child_reg.size = ((uint64_t)reg[2] << 32) | reg[3]; 100 101 sc->sc_iot = faa->fa_iot; 102 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, faa->fa_reg[0].size, 103 0, &sc->sc_ioh)) { 104 printf(": could not map registers\n"); 105 goto error; 106 } 107 108 val = bus_space_read_8(sc->sc_iot, sc->sc_ioh, SCTL_SHIM_CFG); 109 val &= ~SCTL_SHIM_CFG_CSR_BYTE_SWAP; 110 val &= ~SCTL_SHIM_CFG_DMA_BYTE_SWAP; 111 val |= 3ul << SCTL_SHIM_CFG_CSR_BYTE_SWAP_SHIFT; 112 val |= 1ul << SCTL_SHIM_CFG_DMA_BYTE_SWAP_SHIFT; 113 val |= SCTL_SHIM_CFG_READ_CMD; 114 bus_space_write_8(sc->sc_iot, sc->sc_ioh, SCTL_SHIM_CFG, val); 115 (void)bus_space_read_8(sc->sc_iot, sc->sc_ioh, SCTL_SHIM_CFG); 116 117 printf("\n"); 118 119 memset(&child_faa, 0, sizeof(child_faa)); 120 child_faa.fa_name = ""; 121 child_faa.fa_node = child; 122 child_faa.fa_iot = faa->fa_iot; 123 child_faa.fa_dmat = faa->fa_dmat; 124 child_faa.fa_reg = &child_reg; 125 child_faa.fa_nreg = 1; 126 /* child_faa.fa_intr is not utilized. */ 127 128 config_found(self, &child_faa, NULL); 129 130 return; 131 132 error: 133 if (sc->sc_ioh != 0) 134 bus_space_unmap(sc->sc_iot, sc->sc_ioh, faa->fa_reg[0].size); 135 } 136