ralink_cfi.c revision 1.2
1/* $NetBSD: ralink_cfi.c,v 1.2 2023/05/10 00:07:58 riastradh Exp $ */ 2/*- 3 * Copyright (c) 2011 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Cliff Neighbors. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31/* 32 * NOR CFI driver support for ralink 33 */ 34 35#include "opt_flash.h" 36#include "locators.h" 37 38#include <sys/cdefs.h> 39__KERNEL_RCSID(0, "$NetBSD: ralink_cfi.c,v 1.2 2023/05/10 00:07:58 riastradh Exp $"); 40 41#include <sys/param.h> 42#include <sys/systm.h> 43#include <sys/cdefs.h> 44#include <sys/device.h> 45#include <sys/endian.h> 46 47#include <sys/bus.h> 48 49#include <mips/ralink/ralink_var.h> 50#include <mips/ralink/ralink_reg.h> 51 52#include <dev/nor/nor.h> 53#include <dev/nor/cfi.h> 54 55 56static int ra_cfi_match(device_t, cfdata_t, void *); 57static void ra_cfi_attach(device_t, device_t, void *); 58static int ra_cfi_detach(device_t, int); 59 60struct ra_cfi_softc { 61 device_t sc_dev; 62 device_t sc_nordev; 63 struct cfi sc_cfi; 64 bus_addr_t sc_addr; 65 bus_size_t sc_size; 66 struct nor_interface sc_nor_if; 67}; 68 69CFATTACH_DECL_NEW(ralink_cfi, sizeof(struct ra_cfi_softc), ra_cfi_match, 70 ra_cfi_attach, ra_cfi_detach, NULL); 71 72/* 73 * ra_cfi_addr - return bus address for the CFI NOR flash 74 */ 75static inline bus_addr_t 76ra_cfi_addr(struct mainbus_attach_args * const ma) 77{ 78 return RA_FLASH_BASE; /* XXX configure TBD */ 79} 80 81static int 82ra_cfi_match(device_t parent, cfdata_t match, void *aux) 83{ 84 struct mainbus_attach_args * const ma = aux; 85 bus_size_t tmpsize = CFI_QRY_MIN_MAP_SIZE; 86 bus_addr_t addr; 87 struct cfi cfi; 88 int rv; 89 90 KASSERT(ma->ma_memt != NULL); 91 92 addr = ra_cfi_addr(ma); 93#ifdef NOTYET 94 if (addr == MAINBUSCF_ADDR_DEFAULT) { 95 aprint_error("%s: no base address\n", __func__); 96 return 0; 97 } 98#endif 99 100 cfi.cfi_bst = ma->ma_memt; 101 int error = bus_space_map(cfi.cfi_bst, addr, tmpsize, 0, &cfi.cfi_bsh); 102 if (error != 0) { 103 aprint_error("%s: cannot map %#" PRIxBUSSIZE" at offset %#" 104 PRIxBUSADDR ", error %d\n", __func__, tmpsize, addr, error); 105 return false; 106 } 107 108 if (! cfi_probe(&cfi)) { 109 aprint_debug("%s: probe addr %#" PRIxBUSADDR 110 ", CFI not found\n", __func__, addr); 111 rv = 0; 112 } else { 113 rv = 1; 114 } 115 116 bus_space_unmap(cfi.cfi_bst, cfi.cfi_bsh, tmpsize); 117 118 return rv; 119} 120 121static void 122ra_cfi_attach(device_t parent, device_t self, void *aux) 123{ 124 struct ra_cfi_softc *sc = device_private(self); 125 struct mainbus_attach_args * const ma = aux; 126 struct cfi_query_data * const qryp = &sc->sc_cfi.cfi_qry_data; 127 const bus_size_t tmpsize = CFI_QRY_MIN_MAP_SIZE; 128 bool found; 129 int error; 130 131 aprint_normal("\n"); 132 133 sc->sc_dev = self; 134 sc->sc_cfi.cfi_bst = ma->ma_memt; 135 sc->sc_addr = ra_cfi_addr(ma); 136 137 /* map enough to identify, remap later when size is known */ 138 error = bus_space_map(sc->sc_cfi.cfi_bst, sc->sc_addr, tmpsize, 139 0, &sc->sc_cfi.cfi_bsh); 140 if (error != 0) { 141 aprint_error_dev(self, "could not map error %d\n", error); 142 return; 143 } 144 145 found = cfi_identify(&sc->sc_cfi); 146 147 bus_space_unmap(sc->sc_cfi.cfi_bst, sc->sc_cfi.cfi_bsh, tmpsize); 148 149 if (! found) { 150 /* should not happen, we already probed OK in match */ 151 aprint_error_dev(self, "could not map error %d\n", error); 152 return; 153 } 154 155 sc->sc_size = 1 << qryp->device_size; 156 157 sc->sc_nor_if = nor_interface_cfi; 158 sc->sc_nor_if.private = &sc->sc_cfi; 159 sc->sc_nor_if.access_width = (1 << sc->sc_cfi.cfi_portwidth); 160 161 cfi_print(self, &sc->sc_cfi); 162 163 error = bus_space_map(sc->sc_cfi.cfi_bst, sc->sc_addr, sc->sc_size, 164 0, &sc->sc_cfi.cfi_bsh); 165 if (error != 0) { 166 aprint_error_dev(self, "could not map error %d\n", error); 167 return; 168 } 169 170 if (! pmf_device_register1(self, NULL, NULL, NULL)) 171 aprint_error_dev(self, "couldn't establish power handler\n"); 172 173 sc->sc_nordev = nor_attach_mi(&sc->sc_nor_if, self); 174 175} 176 177static int 178ra_cfi_detach(device_t self, int flags) 179{ 180 struct ra_cfi_softc *sc = device_private(self); 181 int error; 182 183 error = config_detach_children(self, flags); 184 if (error) 185 return error; 186 187 pmf_device_deregister(self); 188 189 bus_space_unmap(sc->sc_cfi.cfi_bst, sc->sc_cfi.cfi_bsh, sc->sc_size); 190 191 return 0; 192} 193