Module Name: src Committed By: hkenken Date: Mon Aug 19 11:41:36 UTC 2019
Modified Files: src/sys/arch/arm/imx: imx51_spi.c imx51reg.h imxspi.c imxspivar.h src/sys/arch/arm/imx/fdt: files.imx6 src/sys/arch/evbarm/conf: IMX src/sys/arch/evbarm/netwalker: netwalker_spi.c Added Files: src/sys/arch/arm/imx/fdt: imx6_spi.c Log Message: Add support SPI driver for i.MX6. To generate a diff of this commit: cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/imx/imx51_spi.c \ src/sys/arch/arm/imx/imxspivar.h cvs rdiff -u -r1.7 -r1.8 src/sys/arch/arm/imx/imx51reg.h cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/imx/imxspi.c cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/imx/fdt/files.imx6 cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/imx/fdt/imx6_spi.c cvs rdiff -u -r1.3 -r1.4 src/sys/arch/evbarm/conf/IMX cvs rdiff -u -r1.2 -r1.3 src/sys/arch/evbarm/netwalker/netwalker_spi.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/imx/imx51_spi.c diff -u src/sys/arch/arm/imx/imx51_spi.c:1.1 src/sys/arch/arm/imx/imx51_spi.c:1.2 --- src/sys/arch/arm/imx/imx51_spi.c:1.1 Sat Mar 22 09:28:08 2014 +++ src/sys/arch/arm/imx/imx51_spi.c Mon Aug 19 11:41:36 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: imx51_spi.c,v 1.1 2014/03/22 09:28:08 hkenken Exp $ */ +/* $NetBSD: imx51_spi.c,v 1.2 2019/08/19 11:41:36 hkenken Exp $ */ /*- * Copyright (c) 2014 Genetec Corporation. All rights reserved. @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: imx51_spi.c,v 1.1 2014/03/22 09:28:08 hkenken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: imx51_spi.c,v 1.2 2019/08/19 11:41:36 hkenken Exp $"); #include "locators.h" #include "opt_imx.h" @@ -43,7 +43,8 @@ __KERNEL_RCSID(0, "$NetBSD: imx51_spi.c, #include <arm/imx/imx51_ccmvar.h> struct imx51spi_softc { - struct imxspi_softc sc_spi; + struct imxspi_softc sc_spi; /* Must be first */ + struct spi_chipset_tag sc_tag; }; @@ -74,26 +75,39 @@ imxspi_match(device_t parent, cfdata_t c void imxspi_attach(device_t parent, device_t self, void *aux) { - struct imx51spi_softc *sc = device_private(self); + struct imx51spi_softc *isc = device_private(self); + struct imxspi_softc *sc = &isc->sc_spi; struct axi_attach_args *aa = aux; struct imxspi_attach_args saa; int cf_flags = device_cfdata(self)->cf_flags; + bus_addr_t addr; + bus_size_t size; + int error; + + addr = aa->aa_addr; + size = aa->aa_size; + if (size <= 0) + size = SPI_SIZE; sc->sc_tag.cookie = sc; sc->sc_tag.spi_cs_enable = imxspi_cs_enable; sc->sc_tag.spi_cs_disable = imxspi_cs_disable; - saa.saa_iot = aa->aa_iot; - saa.saa_addr = aa->aa_addr; - saa.saa_size = aa->aa_size; - saa.saa_irq = aa->aa_irq; - saa.saa_enhanced = cf_flags; - - saa.saa_nslaves = IMXSPINSLAVES; - saa.saa_freq = imx51_get_clock(IMX51CLK_CSPI_CLK_ROOT); - saa.saa_tag = &sc->sc_tag; + sc->sc_iot = aa->aa_iot; + sc->sc_enhanced = cf_flags; - sc->sc_spi.sc_dev = self; + sc->sc_nslaves = IMXSPINSLAVES; + sc->sc_freq = imx51_get_clock(IMX51CLK_CSPI_CLK_ROOT); + sc->sc_tag = &sc->sc_tag; + + if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh)) { + aprint_error_dev(sc->sc_dev, "couldn't map registers\n"); + return; + } + + /* enable device interrupts */ + sc->sc_ih = intr_establish(aa->aa_irq, IPL_BIO, IST_LEVEL, + imxspi_intr, sc); - imxspi_attach_common(parent, &sc->sc_spi, &saa); + imxspi_attach_common(self); } Index: src/sys/arch/arm/imx/imxspivar.h diff -u src/sys/arch/arm/imx/imxspivar.h:1.1 src/sys/arch/arm/imx/imxspivar.h:1.2 --- src/sys/arch/arm/imx/imxspivar.h:1.1 Sat Mar 22 09:28:08 2014 +++ src/sys/arch/arm/imx/imxspivar.h Mon Aug 19 11:41:36 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: imxspivar.h,v 1.1 2014/03/22 09:28:08 hkenken Exp $ */ +/* $NetBSD: imxspivar.h,v 1.2 2019/08/19 11:41:36 hkenken Exp $ */ /* * Copyright (c) 2014 Genetec Corporation. All rights reserved. @@ -38,21 +38,10 @@ typedef struct spi_chipset_tag { int (*spi_cs_disable)(void *, int); } *spi_chipset_tag_t; -struct imxspi_attach_args { - bus_space_tag_t saa_iot; - bus_addr_t saa_addr; - bus_size_t saa_size; - int saa_irq; - - spi_chipset_tag_t saa_tag; - int saa_nslaves; - unsigned long saa_freq; - - int saa_enhanced; -}; - struct imxspi_softc { device_t sc_dev; + int sc_phandle; + bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; spi_chipset_tag_t sc_tag; @@ -66,10 +55,12 @@ struct imxspi_softc { bool sc_running; SIMPLEQ_HEAD(,spi_transfer) sc_q; + int sc_nslaves; int sc_enhanced; }; -int imxspi_attach_common(device_t, struct imxspi_softc *, void *); +int imxspi_attach_common(device_t); +int imxspi_intr(void *); /* * defined in machine dependent code Index: src/sys/arch/arm/imx/imx51reg.h diff -u src/sys/arch/arm/imx/imx51reg.h:1.7 src/sys/arch/arm/imx/imx51reg.h:1.8 --- src/sys/arch/arm/imx/imx51reg.h:1.7 Thu May 7 04:37:29 2015 +++ src/sys/arch/arm/imx/imx51reg.h Mon Aug 19 11:41:36 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: imx51reg.h,v 1.7 2015/05/07 04:37:29 hkenken Exp $ */ +/* $NetBSD: imx51reg.h,v 1.8 2019/08/19 11:41:36 hkenken Exp $ */ /*- * Copyright (c) 2007 The NetBSD Foundation, Inc. * All rights reserved. @@ -140,7 +140,6 @@ #define ECSPI1_BASE (AIPSTZ1_BASE + 0x00010000) #define ECSPI2_BASE (AIPSTZ2_BASE + 0x03fac000) -#define ECSPI_SIZE 0x4000 #define SSI1_BASE (AIPSTZ2_BASE + 0x03fcc000) #define SSI2_BASE (AIPSTZ1_BASE + 0x00014000) Index: src/sys/arch/arm/imx/imxspi.c diff -u src/sys/arch/arm/imx/imxspi.c:1.4 src/sys/arch/arm/imx/imxspi.c:1.5 --- src/sys/arch/arm/imx/imxspi.c:1.4 Tue Aug 13 17:03:10 2019 +++ src/sys/arch/arm/imx/imxspi.c Mon Aug 19 11:41:36 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: imxspi.c,v 1.4 2019/08/13 17:03:10 tnn Exp $ */ +/* $NetBSD: imxspi.c,v 1.5 2019/08/19 11:41:36 hkenken Exp $ */ /*- * Copyright (c) 2014 Genetec Corporation. All rights reserved. @@ -32,10 +32,11 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: imxspi.c,v 1.4 2019/08/13 17:03:10 tnn Exp $"); +__KERNEL_RCSID(0, "$NetBSD: imxspi.c,v 1.5 2019/08/19 11:41:36 hkenken Exp $"); #include "opt_imx.h" #include "opt_imxspi.h" +#include "opt_fdt.h" #include <sys/param.h> #include <sys/systm.h> @@ -52,11 +53,14 @@ __KERNEL_RCSID(0, "$NetBSD: imxspi.c,v 1 #include <arm/imx/imxspivar.h> #include <arm/imx/imxspireg.h> +#ifdef FDT +#include <dev/fdt/fdtvar.h> +#endif + /* SPI service routines */ static int imxspi_configure_enhanced(void *, int, int, int); static int imxspi_configure(void *, int, int, int); static int imxspi_transfer(void *, struct spi_transfer *); -static int imxspi_intr(void *); /* internal stuff */ void imxspi_done(struct imxspi_softc *, int); @@ -78,30 +82,30 @@ int imxspi_debug = IMXSPI_DEBUG; #define DPRINTFN(n,x) #endif -int -imxspi_attach_common(device_t parent, struct imxspi_softc *sc, void *aux) +#ifdef FDT +static struct spi_controller * +imxspi_get_controller(device_t dev) { - struct imxspi_attach_args *saa = aux; - struct spibus_attach_args sba; - bus_addr_t addr = saa->saa_addr; - bus_size_t size = saa->saa_size; + struct imxspi_softc * const sc = device_private(dev); - sc->sc_iot = saa->saa_iot; - sc->sc_freq = saa->saa_freq; - sc->sc_tag = saa->saa_tag; - sc->sc_enhanced = saa->saa_enhanced; - if (size <= 0) - size = SPI_SIZE; - - if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh)) { - aprint_error_dev(sc->sc_dev, "couldn't map registers\n"); - return 1; - } + return &sc->sc_spi; +} + +static const struct fdtbus_spi_controller_func imxspi_funcs = { + .get_controller = imxspi_get_controller +}; +#endif + +int +imxspi_attach_common(device_t self) +{ + struct imxspi_softc * const sc = device_private(self); - aprint_normal(": i.MX %sCSPI Controller (clock %ld Hz)\n", + aprint_normal("i.MX %sCSPI Controller (clock %ld Hz)\n", ((sc->sc_enhanced) ? "e" : ""), sc->sc_freq); /* Initialize SPI controller */ + sc->sc_dev = self; sc->sc_spi.sct_cookie = sc; if (sc->sc_enhanced) sc->sc_spi.sct_configure = imxspi_configure_enhanced; @@ -110,13 +114,10 @@ imxspi_attach_common(device_t parent, st sc->sc_spi.sct_transfer = imxspi_transfer; /* sc->sc_spi.sct_nslaves must have been initialized by machdep code */ - sc->sc_spi.sct_nslaves = saa->saa_nslaves; + sc->sc_spi.sct_nslaves = sc->sc_nslaves; if (!sc->sc_spi.sct_nslaves) aprint_error_dev(sc->sc_dev, "no slaves!\n"); - memset(&sba, 0, sizeof(sba)); - sba.sba_controller = &sc->sc_spi; - /* initialize the queue */ SIMPLEQ_INIT(&sc->sc_q); @@ -132,12 +133,19 @@ imxspi_attach_common(device_t parent, st WRITE_REG(sc, PERIODREG, 0x0); - /* enable device interrupts */ - sc->sc_ih = intr_establish(saa->saa_irq, IPL_BIO, IST_LEVEL, - imxspi_intr, sc); +#ifdef FDT + KASSERT(sc->sc_phandle != 0); + + fdtbus_register_spi_controller(self, sc->sc_phandle, &imxspi_funcs); + (void) fdtbus_attach_spibus(self, sc->sc_phandle, spibus_print); +#else + struct spibus_attach_args sba; + memset(&sba, 0, sizeof(sba)); + sba.sba_controller = &sc->sc_spi; /* attach slave devices */ (void)config_found_ia(sc->sc_dev, "spibus", &sba, spibus_print); +#endif return 0; } @@ -363,7 +371,7 @@ imxspi_done(struct imxspi_softc *sc, int imxspi_sched(sc); } -static int +int imxspi_intr(void *arg) { struct imxspi_softc *sc = arg; Index: src/sys/arch/arm/imx/fdt/files.imx6 diff -u src/sys/arch/arm/imx/fdt/files.imx6:1.5 src/sys/arch/arm/imx/fdt/files.imx6:1.6 --- src/sys/arch/arm/imx/fdt/files.imx6:1.5 Mon Aug 12 11:45:53 2019 +++ src/sys/arch/arm/imx/fdt/files.imx6 Mon Aug 19 11:41:36 2019 @@ -1,4 +1,4 @@ -# $NetBSD: files.imx6,v 1.5 2019/08/12 11:45:53 skrll Exp $ +# $NetBSD: files.imx6,v 1.6 2019/08/19 11:41:36 hkenken Exp $ # # Configuration info for the Freescale i.MX6 # @@ -76,3 +76,11 @@ device imxi2c: motoi2c, i2cbus, i2cexec attach imxi2c at fdt file arch/arm/imx/imxi2c.c imxi2c file arch/arm/imx/fdt/imx6_i2c.c imxi2c + +# SPI bus controlloer +device imxspi : spibus +attach imxspi at fdt with imxspi_fdt +file arch/arm/imx/imxspi.c imxspi +file arch/arm/imx/fdt/imx6_spi.c imxspi_fdt +defparam opt_imxspi.h IMXSPINSLAVES + Index: src/sys/arch/evbarm/conf/IMX diff -u src/sys/arch/evbarm/conf/IMX:1.3 src/sys/arch/evbarm/conf/IMX:1.4 --- src/sys/arch/evbarm/conf/IMX:1.3 Mon Aug 12 11:46:39 2019 +++ src/sys/arch/evbarm/conf/IMX Mon Aug 19 11:41:36 2019 @@ -1,5 +1,5 @@ # -# $NetBSD: IMX,v 1.3 2019/08/12 11:46:39 skrll Exp $ +# $NetBSD: IMX,v 1.4 2019/08/19 11:41:36 hkenken Exp $ # # NXP(Freescale) I.MX family SoCs # @@ -15,6 +15,7 @@ makeoptions DTS=" imx6dl-hummingboard.dts imx6q-hummingboard2.dts imx6dl-hummingboard2.dts + imx6qp-sabresd.dts " options MULTIPROCESSOR @@ -136,5 +137,14 @@ pci* at ppb? imxi2c* at fdt? iic* at imxi2c? +# SPI +imxspi* at fdt? +spi* at imxspi? +options IMXSPINSLAVES=1 + +# SPI NOR-Flash +spiflash* at spiflashbus? +m25p* at spi? slave ? + cinclude "arch/evbarm/conf/IMX.local" Index: src/sys/arch/evbarm/netwalker/netwalker_spi.c diff -u src/sys/arch/evbarm/netwalker/netwalker_spi.c:1.2 src/sys/arch/evbarm/netwalker/netwalker_spi.c:1.3 --- src/sys/arch/evbarm/netwalker/netwalker_spi.c:1.2 Wed Jul 24 12:33:18 2019 +++ src/sys/arch/evbarm/netwalker/netwalker_spi.c Mon Aug 19 11:41:36 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: netwalker_spi.c,v 1.2 2019/07/24 12:33:18 hkenken Exp $ */ +/* $NetBSD: netwalker_spi.c,v 1.3 2019/08/19 11:41:36 hkenken Exp $ */ /*- * Copyright (c) 2009 Genetec Corporation. All rights reserved. @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: netwalker_spi.c,v 1.2 2019/07/24 12:33:18 hkenken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: netwalker_spi.c,v 1.3 2019/08/19 11:41:36 hkenken Exp $"); #include "opt_imxspi.h" @@ -45,9 +45,11 @@ __KERNEL_RCSID(0, "$NetBSD: netwalker_sp #include <arm/imx/imx51_iomuxreg.h> #include <arm/imx/imxgpiovar.h> #include <arm/imx/imxspivar.h> +#include <arm/imx/imxspireg.h> struct imx51spi_softc { - struct imxspi_softc sc_spi; + struct imxspi_softc sc_spi; /* Must be first */ + struct spi_chipset_tag sc_tag; }; @@ -110,14 +112,22 @@ imxspi_match(device_t parent, cfdata_t c void imxspi_attach(device_t parent, device_t self, void *aux) { - struct imx51spi_softc *sc = device_private(self); + struct imx51spi_softc *isc = device_private(self); + struct imxspi_softc *sc = &isc->sc_spi; struct axi_attach_args *aa = aux; - struct imxspi_attach_args saa; int cf_flags = device_cfdata(self)->cf_flags; + bus_addr_t addr; + bus_size_t size; + + addr = aa->aa_addr; + size = aa->aa_size; + if (size <= 0) + size = SPI_SIZE; - sc->sc_tag.cookie = sc; + isc->sc_tag.cookie = sc; - if (device_cfdata(self)->cf_unit == 0) { + switch (device_unit(self)) { + case 0: /* CS 0 GPIO setting */ gpio_data_write(GPIO_NO(4, 24), GPIO_PIN_HIGH); gpio_set_direction(GPIO_NO(4, 24), GPIO_PIN_INPUT); @@ -135,21 +145,26 @@ imxspi_attach(device_t parent, device_t gpio_data_write(GPIO_NO(3, 0), GPIO_PIN_HIGH); gpio_set_direction(GPIO_NO(3, 0), GPIO_PIN_INPUT); - sc->sc_tag.spi_cs_enable = imxspi_cs_enable; - sc->sc_tag.spi_cs_disable = imxspi_cs_disable; + isc->sc_tag.spi_cs_enable = imxspi_cs_enable; + isc->sc_tag.spi_cs_disable = imxspi_cs_disable; + break; } - saa.saa_iot = aa->aa_iot; - saa.saa_addr = aa->aa_addr; - saa.saa_size = aa->aa_size; - saa.saa_irq = aa->aa_irq; - saa.saa_enhanced = cf_flags; - - saa.saa_nslaves = IMXSPINSLAVES; - saa.saa_freq = imx51_get_clock(IMX51CLK_CSPI_CLK_ROOT); - saa.saa_tag = &sc->sc_tag; + sc->sc_iot = aa->aa_iot; + sc->sc_enhanced = cf_flags; + + sc->sc_nslaves = IMXSPINSLAVES; + sc->sc_freq = imx51_get_clock(IMX51CLK_CSPI_CLK_ROOT); + sc->sc_tag = &isc->sc_tag; + + if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh)) { + aprint_error_dev(sc->sc_dev, "couldn't map registers\n"); + return; + } - sc->sc_spi.sc_dev = self; + /* enable device interrupts */ + sc->sc_ih = intr_establish(aa->aa_irq, IPL_BIO, IST_LEVEL, + imxspi_intr, sc); - imxspi_attach_common(parent, &sc->sc_spi, &saa); + imxspi_attach_common(self); } Added files: Index: src/sys/arch/arm/imx/fdt/imx6_spi.c diff -u /dev/null src/sys/arch/arm/imx/fdt/imx6_spi.c:1.1 --- /dev/null Mon Aug 19 11:41:36 2019 +++ src/sys/arch/arm/imx/fdt/imx6_spi.c Mon Aug 19 11:41:36 2019 @@ -0,0 +1,156 @@ +/* $NetBSD: imx6_spi.c,v 1.1 2019/08/19 11:41:36 hkenken Exp $ */ +/*- + * Copyright (c) 2019 Genetec Corporation. All rights reserved. + * Written by Hashimoto Kenichi for Genetec Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: imx6_spi.c,v 1.1 2019/08/19 11:41:36 hkenken Exp $"); + +#include "opt_imxspi.h" + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/device.h> +#include <sys/kmem.h> +#include <sys/gpio.h> + +#include <arm/imx/imxspivar.h> + +#include <dev/fdt/fdtvar.h> + +struct imxspi_fdt_softc { + struct imxspi_softc sc_imxspi; /* Must be first */ + + struct spi_chipset_tag sc_tag; + struct clk *sc_clk; + + struct fdtbus_gpio_pin **sc_pin_cs; +}; + +static const struct of_compat_data compat_data[] = { + { "fsl,imx6q-ecspi", true }, + { NULL } +}; + +CFATTACH_DECL_NEW(imxspi_fdt, sizeof(struct imxspi_fdt_softc), + imxspi_match, imxspi_attach, NULL, NULL); + +static int +imxspi_cs_enable(void *arg, int slave) +{ + struct imxspi_fdt_softc * const sc = arg; + fdtbus_gpio_write(sc->sc_pin_cs[slave], 1); + return 0; +} + +static int +imxspi_cs_disable(void *arg, int slave) +{ + struct imxspi_fdt_softc * const sc = arg; + fdtbus_gpio_write(sc->sc_pin_cs[slave], 0); + return 0; +} + +int +imxspi_match(device_t parent, cfdata_t cf, void *aux) +{ + struct fdt_attach_args * const faa = aux; + + return of_match_compat_data(faa->faa_phandle, compat_data); +} + +void +imxspi_attach(device_t parent, device_t self, void *aux) +{ + struct imxspi_fdt_softc * const ifsc = device_private(self); + struct imxspi_softc * const sc = &ifsc->sc_imxspi; + struct fdt_attach_args * const faa = aux; + char intrstr[128]; + const int phandle = faa->faa_phandle; + bus_addr_t addr; + bus_size_t size; + int error; + + u_int nslaves; + error = of_getprop_uint32(phandle, "fsl,spi-num-chipselects", &nslaves); + if (error) + nslaves = IMXSPINSLAVES; + + ifsc->sc_pin_cs = kmem_alloc(sizeof(struct fdtbus_gpio_pin *) * nslaves, KM_SLEEP); + + for (int i = 0; i < nslaves; i++) { + ifsc->sc_pin_cs[i] = fdtbus_gpio_acquire_index(phandle, "cs-gpios", i, + GPIO_PIN_OUTPUT); + } + + ifsc->sc_clk = fdtbus_clock_get_index(phandle, 0); + if (ifsc->sc_clk == NULL) { + aprint_error(": couldn't get clock\n"); + return; + } + + error = clk_enable(ifsc->sc_clk); + if (error) { + aprint_error_dev(sc->sc_dev, "couldn't enable: %d\n", error); + return; + } + + ifsc->sc_tag.cookie = ifsc; + ifsc->sc_tag.spi_cs_enable = imxspi_cs_enable; + ifsc->sc_tag.spi_cs_disable = imxspi_cs_disable; + + sc->sc_phandle = phandle; + sc->sc_iot = faa->faa_bst; + sc->sc_enhanced = of_search_compatible(phandle, compat_data)->data; + + sc->sc_nslaves = nslaves; + sc->sc_freq = clk_get_rate(ifsc->sc_clk); + sc->sc_tag = &ifsc->sc_tag; + + if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { + aprint_error(": couldn't get iomux registers\n"); + return; + } + + if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh)) { + aprint_error_dev(sc->sc_dev, "couldn't map registers\n"); + return; + } + + if (!fdtbus_intr_str(faa->faa_phandle, 0, intrstr, sizeof(intrstr))) { + aprint_error_dev(self, "failed to decode interrupt\n"); + return; + } + + sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_VM, + FDT_INTR_MPSAFE, imxspi_intr, &ifsc->sc_imxspi); + if (sc->sc_ih == NULL) { + aprint_error_dev(self, "couldn't establish interrupt on %s\n", + intrstr); + return; + } + aprint_normal_dev(self, "interrupting on %s\n", intrstr); + + imxspi_attach_common(self); +}