118334Speter/* $NetBSD: flash_cfi.c,v 1.5 2023/05/10 00:08:14 riastradh Exp $ */ 290285Sobrien 3169699Skan/*- 4169699Skan * Copyright (c) 2011 Frank Wille. 518334Speter * All rights reserved. 690285Sobrien * 718334Speter * Written by Frank Wille for The NetBSD Project. 890285Sobrien * 990285Sobrien * Redistribution and use in source and binary forms, with or without 1090285Sobrien * modification, are permitted provided that the following conditions 1190285Sobrien * are met: 1218334Speter * 1. Redistributions of source code must retain the above copyright 1390285Sobrien * notice, this list of conditions and the following disclaimer. 1490285Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1590285Sobrien * notice, this list of conditions and the following disclaimer in the 1690285Sobrien * documentation and/or other materials provided with the distribution. 1718334Speter * 1818334Speter * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 1990285Sobrien * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20169699Skan * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21169699Skan * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 2218334Speter * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2318334Speter * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2418334Speter * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2518334Speter * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2618334Speter * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2718334Speter * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2818334Speter * POSSIBILITY OF SUCH DAMAGE. 2918334Speter */ 3018334Speter 31169699Skan/* 3218334Speter * NOR CFI driver support for sandpoint 3318334Speter */ 3418334Speter#include <sys/cdefs.h> 3518334Speter__KERNEL_RCSID(0, "$NetBSD: flash_cfi.c,v 1.5 2023/05/10 00:08:14 riastradh Exp $"); 3618334Speter 3718334Speter#include <sys/param.h> 3818334Speter#include <sys/device.h> 3918334Speter 4018334Speter#include <machine/autoconf.h> 4118334Speter 4218334Speter#include <dev/nor/nor.h> 4318334Speter#include <dev/nor/cfi.h> 4418334Speter 4518334Speter 4618334Speterstatic int sandpointcfi_probe(device_t, cfdata_t, void *); 4718334Speterstatic void sandpointcfi_attach(device_t, device_t, void *); 4818334Speterstatic int sandpointcfi_detach(device_t, int); 4918334Speter 5018334Speterstruct sandpointcfi_softc { 5118334Speter device_t sc_dev; 5218334Speter device_t sc_nordev; 5318334Speter struct cfi sc_cfi; 5418334Speter bus_size_t sc_size; 5518334Speter struct nor_interface sc_nor_if; 5618334Speter}; 5718334Speter 5818334SpeterCFATTACH_DECL_NEW(sandpointcfi, sizeof(struct sandpointcfi_softc), 5918334Speter sandpointcfi_probe, sandpointcfi_attach, sandpointcfi_detach, NULL); 6018334Speter 6118334Speterstatic int 6218334Spetersandpointcfi_probe(device_t parent, cfdata_t cf, void *aux) 6318334Speter{ 6418334Speter extern struct cfdriver cfi_cd; 6518334Speter struct mainbus_attach_args *ma = aux; 6618334Speter const bus_size_t qrysize = CFI_QRY_MIN_MAP_SIZE; 6718334Speter struct cfi cfi; 6818334Speter int error, rv; 6918334Speter 7018334Speter if (strcmp(ma->ma_name, cfi_cd.cd_name) != 0) 7118334Speter return 0; 7218334Speter 7318334Speter KASSERT(ma->ma_bst != NULL); 7418334Speter 7518334Speter cfi.cfi_bst = ma->ma_bst; 7618334Speter 7718334Speter /* flash should be at least 2 MiB in size at 0xffe00000 */ 7818334Speter error = bus_space_map(cfi.cfi_bst, 0xffe00000, qrysize, 0, 7918334Speter &cfi.cfi_bsh); 8018334Speter if (error != 0) { 8118334Speter aprint_error("%s: cannot map %d at offset %#x, error %d\n", 8218334Speter __func__, qrysize, ma->ma_addr, error); 8318334Speter return 0; 8418334Speter } 8518334Speter 8618334Speter /* probe for NOR flash */ 8718334Speter if (!cfi_probe(&cfi)) { 8818334Speter aprint_debug("%s: probe addr %#x, CFI not found\n", 8918334Speter __func__, ma->ma_addr); 9018334Speter rv = 0; 9118334Speter } else 9250605Sobrien rv = 1; 93132727Skan 94132727Skan bus_space_unmap(cfi.cfi_bst, cfi.cfi_bsh, qrysize); 9518334Speter return rv; 9690285Sobrien} 9718334Speter 9890285Sobrienstatic void 9990285Sobriensandpointcfi_attach(device_t parent, device_t self, void *aux) 10018334Speter{ 10118334Speter struct mainbus_attach_args *ma = aux; 10218334Speter struct sandpointcfi_softc *sc; 103169699Skan const bus_size_t qrysize = CFI_QRY_MIN_MAP_SIZE; 10418334Speter bus_addr_t addr; 10518334Speter bool found; 10618334Speter int error; 10718334Speter 10890285Sobrien aprint_naive("\n"); 10950605Sobrien aprint_normal("\n"); 110132727Skan 111169699Skan sc = device_private(self); 11218334Speter sc->sc_dev = self; 113169699Skan sc->sc_cfi.cfi_bst = ma->ma_bst; 114169699Skan 115169699Skan /* map enough to identify, remap later when size is known */ 116169699Skan error = bus_space_map(sc->sc_cfi.cfi_bst, 0xffe00000, qrysize, 0, 117169699Skan &sc->sc_cfi.cfi_bsh); 11850605Sobrien if (error != 0) { 119169699Skan aprint_error_dev(self, "could not map error %d\n", error); 120169699Skan return; 121169699Skan } 122169699Skan 123169699Skan /* identify the NOR flash */ 124169699Skan found = cfi_identify(&sc->sc_cfi); 12518334Speter 12690285Sobrien bus_space_unmap(sc->sc_cfi.cfi_bst, sc->sc_cfi.cfi_bsh, qrysize); 12790285Sobrien if (!found) { 12818334Speter /* should not happen, we already probed OK in match */ 12990285Sobrien aprint_error_dev(self, "could not map error %d\n", error); 13018334Speter return; 13118334Speter } 13218334Speter 13318334Speter /* get size of flash in bytes */ 13418334Speter sc->sc_size = 1 << sc->sc_cfi.cfi_qry_data.device_size; 13518334Speter 13618334Speter /* determine real base address */ 13718334Speter addr = (0xffffffff - sc->sc_size) + 1; 13818334Speter 13918334Speter sc->sc_nor_if = nor_interface_cfi; 14018334Speter sc->sc_nor_if.private = &sc->sc_cfi; 14118334Speter sc->sc_nor_if.access_width = (1 << sc->sc_cfi.cfi_portwidth); 14218334Speter 14318334Speter cfi_print(self, &sc->sc_cfi); 14418334Speter 14518334Speter error = bus_space_map(sc->sc_cfi.cfi_bst, addr, sc->sc_size, 0, 14618334Speter &sc->sc_cfi.cfi_bsh); 14718334Speter if (error != 0) { 14818334Speter aprint_error_dev(self, "could not map error %d\n", error); 14918334Speter return; 15018334Speter } 15118334Speter 15218334Speter if (!pmf_device_register1(self, NULL, NULL, NULL)) 15318334Speter aprint_error_dev(self, "couldn't establish power handler\n"); 15418334Speter 15518334Speter sc->sc_nordev = nor_attach_mi(&sc->sc_nor_if, self); 15618334Speter} 15718334Speter 15818334Speterstatic int 15918334Spetersandpointcfi_detach(device_t self, int flags) 16018334Speter{ 16118334Speter struct sandpointcfi_softc *sc device_private(self); 16218334Speter int error; 16318334Speter 16418334Speter error = config_detach_children(self, flags); 16518334Speter if (error) 16650605Sobrien return error; 16750605Sobrien 16850605Sobrien pmf_device_deregister(self); 16950605Sobrien 17018334Speter bus_space_unmap(sc->sc_cfi.cfi_bst, sc->sc_cfi.cfi_bsh, sc->sc_size); 17118334Speter return 0; 17218334Speter} 17318334Speter