Home | History | Annotate | Line # | Download | only in nxp
imx_ahcisata.c revision 1.1
      1 /*	$NetBSD: imx_ahcisata.c,v 1.1 2020/12/23 14:42:38 skrll Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2019 Genetec Corporation.  All rights reserved.
      5  * Written by Hashimoto Kenichi for Genetec Corporation.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: imx_ahcisata.c,v 1.1 2020/12/23 14:42:38 skrll Exp $");
     31 
     32 #include <sys/param.h>
     33 #include <sys/bus.h>
     34 #include <sys/device.h>
     35 #include <sys/intr.h>
     36 #include <sys/systm.h>
     37 #include <sys/kernel.h>
     38 
     39 #include <dev/ata/atavar.h>
     40 #include <dev/ic/ahcisatavar.h>
     41 
     42 #include <arm/nxp/imx_ahcisatareg.h>
     43 #include <arm/nxp/imx6_iomuxreg.h>
     44 #include <arm/nxp/imx6_ccmreg.h>
     45 #include <arm/nxp/imx6_ccmvar.h>
     46 
     47 #include <dev/fdt/fdtvar.h>
     48 
     49 static int imx_ahcisata_match(device_t, cfdata_t, void *);
     50 static void imx_ahcisata_attach(device_t, device_t, void *);
     51 
     52 struct imx_ahcisata_softc {
     53 	struct ahci_softc sc;
     54 
     55 	device_t sc_dev;
     56 	bus_space_tag_t sc_iot;
     57 	bus_space_handle_t sc_ioh;
     58 	bus_space_handle_t sc_gpr_ioh;
     59 	void *sc_ih;
     60 
     61 	u_int sc_tx_level;
     62 	u_int sc_tx_boost;
     63 	u_int sc_tx_atten;
     64 	u_int sc_rx_eq;
     65 	u_int sc_ss;
     66 
     67 	struct clk *sc_clk_sata;
     68 	struct clk *sc_clk_sata_ref;
     69 	struct clk *sc_clk_ahb;
     70 };
     71 
     72 static int imx_ahcisata_init(struct imx_ahcisata_softc *);
     73 static int imx_ahcisata_phy_ctrl(struct imx_ahcisata_softc *, uint32_t, int);
     74 static int imx_ahcisata_phy_addr(struct imx_ahcisata_softc *, uint32_t);
     75 static int imx_ahcisata_phy_write(struct imx_ahcisata_softc *, uint32_t, uint16_t);
     76 static int imx_ahcisata_phy_read(struct imx_ahcisata_softc *, uint32_t);
     77 static int imx_ahcisata_init_clocks(struct imx_ahcisata_softc *);
     78 
     79 CFATTACH_DECL_NEW(imx_ahcisata, sizeof(struct imx_ahcisata_softc),
     80 	imx_ahcisata_match, imx_ahcisata_attach, NULL, NULL);
     81 
     82 static int
     83 imx_ahcisata_match(device_t parent, cfdata_t cf, void *aux)
     84 {
     85 	const char * const compatible[] = { "fsl,imx6q-ahci", NULL };
     86 	struct fdt_attach_args * const faa = aux;
     87 
     88 	return of_match_compatible(faa->faa_phandle, compatible);
     89 }
     90 
     91 static void
     92 imx_ahcisata_attach(device_t parent, device_t self, void *aux)
     93 {
     94 	struct imx_ahcisata_softc * const sc = device_private(self);
     95 	struct fdt_attach_args * const faa = aux;
     96 	const int phandle = faa->faa_phandle;
     97 	bus_addr_t ahci_addr;
     98 	bus_size_t ahci_size;
     99 	bus_addr_t addr;
    100 	bus_size_t size;
    101 	char intrstr[128];
    102 	int error;
    103 
    104 	if (fdtbus_get_reg(phandle, 0, &ahci_addr, &ahci_size) != 0) {
    105 		aprint_error(": couldn't get ahci registers\n");
    106 		return;
    107 	}
    108 
    109 	if (of_getprop_uint32(phandle, "fsl,transmit-level-mV", &sc->sc_tx_level) != 0)
    110 		sc->sc_tx_level = 1104;
    111 	if (of_getprop_uint32(phandle, "fsl,transmit-boost-mdB", &sc->sc_tx_boost) != 0)
    112 		sc->sc_tx_boost = 3330;
    113 	if (of_getprop_uint32(phandle, "fsl,transmit-atten-16ths", &sc->sc_tx_atten) != 0)
    114 		sc->sc_tx_atten = 9;
    115 	if (of_getprop_uint32(phandle, "fsl,receive-eq-mdB", &sc->sc_rx_eq) != 0)
    116 		sc->sc_rx_eq = 3000;
    117 	if (of_getprop_bool(phandle, "fsl,no-spread-spectrum") == false)
    118 		sc->sc_ss = 1;
    119 	else
    120 		sc->sc_ss = 0;
    121 
    122 	sc->sc_clk_sata = fdtbus_clock_get(phandle, "sata");
    123 	if (sc->sc_clk_sata == NULL) {
    124 		aprint_error(": couldn't get clock sata\n");
    125 		return;
    126 	}
    127 	sc->sc_clk_sata_ref = fdtbus_clock_get(phandle, "sata_ref");
    128 	if (sc->sc_clk_sata_ref == NULL) {
    129 		aprint_error(": couldn't get clock sata_ref\n");
    130 		return;
    131 	}
    132 	sc->sc_clk_ahb = fdtbus_clock_get(phandle, "ahb");
    133 	if (sc->sc_clk_ahb == NULL) {
    134 		aprint_error(": couldn't get clock ahb\n");
    135 		return;
    136 	}
    137 
    138 	aprint_naive("\n");
    139 	aprint_normal(": AHCI Controller\n");
    140 
    141 	aprint_debug_dev(self, "tx level %d [mV]\n", sc->sc_tx_level);
    142 	aprint_debug_dev(self, "tx boost %d [mdB]\n", sc->sc_tx_boost);
    143 	aprint_debug_dev(self, "tx atten %d [16ths]\n", sc->sc_tx_atten);
    144 	aprint_debug_dev(self, "rx eq    %d [mdB]\n", sc->sc_rx_eq);
    145 	aprint_debug_dev(self, "ss       %d\n", sc->sc_ss);
    146 
    147 	sc->sc_dev = self;
    148 
    149 	sc->sc.sc_atac.atac_dev = self;
    150 	sc->sc.sc_ahci_ports = 1;
    151 	sc->sc.sc_dmat = faa->faa_dmat;
    152 	sc->sc.sc_ahcit = faa->faa_bst;
    153 	sc->sc.sc_ahcis = ahci_size;
    154 	error = bus_space_map(sc->sc.sc_ahcit, ahci_addr, ahci_size, 0,
    155 	    &sc->sc.sc_ahcih);
    156 	if (error) {
    157 		aprint_error(": couldn't map ahci registers: %d\n", error);
    158 		return;
    159 	}
    160 
    161 	sc->sc_iot = sc->sc.sc_ahcit;
    162 	sc->sc_ioh = sc->sc.sc_ahcih;
    163 
    164 	const int gpr_phandle = OF_finddevice("/soc/aips-bus/iomuxc-gpr");
    165 	fdtbus_get_reg(gpr_phandle, 0, &addr, &size);
    166 	if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_gpr_ioh)) {
    167 		aprint_error_dev(self, "Cannot map registers\n");
    168 		return;
    169 	}
    170 
    171 	if (imx_ahcisata_init_clocks(sc) != 0) {
    172 		aprint_error_dev(self, "couldn't init clocks\n");
    173 		return;
    174 	}
    175 
    176 	if (imx_ahcisata_init(sc) != 0) {
    177 		aprint_error_dev(self, "couldn't init ahci\n");
    178 		return;
    179 	}
    180 
    181 	if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
    182 		aprint_error_dev(self, "failed to decode interrupt\n");
    183 		return;
    184 	}
    185 
    186 	sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_BIO, 0,
    187 	    ahci_intr, &sc->sc);
    188 	if (sc->sc_ih == NULL) {
    189 		aprint_error_dev(self, "failed to establish interrupt on %s\n",
    190 		    intrstr);
    191 		return;
    192 	}
    193 	aprint_normal_dev(self, "interrupting on %s\n", intrstr);
    194 
    195 	ahci_attach(&sc->sc);
    196 }
    197 
    198 static int
    199 imx_ahcisata_phy_ctrl(struct imx_ahcisata_softc *sc, uint32_t bitmask, int on)
    200 {
    201 	uint32_t v;
    202 	int timeout;
    203 
    204 	v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR);
    205 	if (on)
    206 		v |= bitmask;
    207 	else
    208 		v &= ~bitmask;
    209 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR, v);
    210 
    211 	for (timeout = 5000; timeout > 0; --timeout) {
    212 		v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYSR);
    213 		if (!!(v & SATA_P0PHYSR_CR_ACK) == !!on)
    214 			break;
    215 		delay(100);
    216 	}
    217 
    218 	if (timeout > 0)
    219 		return 0;
    220 
    221 	return -1;
    222 }
    223 
    224 static int
    225 imx_ahcisata_phy_addr(struct imx_ahcisata_softc *sc, uint32_t addr)
    226 {
    227 	delay(100);
    228 
    229 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR, addr);
    230 
    231 	if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_ADDR, 1) != 0)
    232 		return -1;
    233 	if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_ADDR, 0) != 0)
    234 		return -1;
    235 
    236 	return 0;
    237 }
    238 
    239 static int
    240 imx_ahcisata_phy_write(struct imx_ahcisata_softc *sc, uint32_t addr,
    241                         uint16_t data)
    242 {
    243 	if (imx_ahcisata_phy_addr(sc, addr) != 0)
    244 		return -1;
    245 
    246 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR, data);
    247 
    248 	if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_DATA, 1) != 0)
    249 		return -1;
    250 	if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_DATA, 0) != 0)
    251 		return -1;
    252 
    253 	if ((addr == SATA_PHY_CLOCK_RESET) && data) {
    254 		/* we can't check ACK after RESET */
    255 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYCR,
    256 		    data | SATA_P0PHYCR_CR_WRITE);
    257 		return 0;
    258 	}
    259 
    260 	if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_WRITE, 1) != 0)
    261 		return -1;
    262 	if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_WRITE, 0) != 0)
    263 		return -1;
    264 
    265 	return 0;
    266 }
    267 
    268 static int
    269 imx_ahcisata_phy_read(struct imx_ahcisata_softc *sc, uint32_t addr)
    270 {
    271 	uint32_t v;
    272 
    273 	if (imx_ahcisata_phy_addr(sc, addr) != 0)
    274 		return -1;
    275 
    276 	if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_READ, 1) != 0)
    277 		return -1;
    278 
    279 	v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_P0PHYSR);
    280 
    281 	if (imx_ahcisata_phy_ctrl(sc, SATA_P0PHYCR_CR_READ, 0) != 0)
    282 		return -1;
    283 
    284 	return SATA_P0PHYSR_CR_DATA_OUT(v);
    285 }
    286 
    287 const static int tx_level[] = {
    288 	 937,
    289 	 947,
    290 	 957,
    291 	 966,
    292 	 976,
    293 	 986,
    294 	 996,
    295 	1005,
    296 	1015,
    297 	1025,
    298 	1035,
    299 	1045,
    300 	1054,
    301 	1064,
    302 	1074,
    303 	1084,
    304 	1094,
    305 	1104,
    306 	1113,
    307 	1123,
    308 	1133,
    309 	1143,
    310 	1152,
    311 	1162,
    312 	1172,
    313 	1182,
    314 	1191,
    315 	1201,
    316 	1211,
    317 	1221,
    318 	1230,
    319 	1240,
    320 };
    321 
    322 const static int tx_boots[] = {
    323 	   0,
    324 	 370,
    325 	 740,
    326 	1110,
    327 	1480,
    328 	1850,
    329 	2220,
    330 	2590,
    331 	2960,
    332 	3330,
    333 	3700,
    334 	4070,
    335 	4440,
    336 	4810,
    337 	5280,
    338 	5750,
    339 };
    340 
    341 const static int tx_atten[] = {
    342 	  16,
    343 	  14,
    344 	  12,
    345 	  10,
    346 	   9,
    347 	   8,
    348 };
    349 
    350 const static int rx_eq[] = {
    351 	 500,
    352 	1000,
    353 	1500,
    354 	2000,
    355 	2500,
    356 	3000,
    357 	3500,
    358 	4000,
    359 };
    360 
    361 static int
    362 imx_ahcisata_search_regval(const int *values, int count, int val)
    363 {
    364 	for (int i = 0; i < count; i++)
    365 		if (values[i] == val)
    366 			return i;
    367 
    368 	return -1;
    369 }
    370 
    371 static int
    372 imx_ahcisata_init(struct imx_ahcisata_softc *sc)
    373 {
    374 	uint32_t v;
    375 	int timeout;
    376 	int pllstat;
    377 
    378 	v = bus_space_read_4(sc->sc_iot, sc->sc_gpr_ioh, IOMUX_GPR13);
    379 	/* clear */
    380 	v &= ~(IOMUX_GPR13_SATA_PHY_8 |
    381 	    IOMUX_GPR13_SATA_PHY_7 |
    382 	    IOMUX_GPR13_SATA_PHY_6 |
    383 	    IOMUX_GPR13_SATA_SPEED |
    384 	    IOMUX_GPR13_SATA_PHY_5 |
    385 	    IOMUX_GPR13_SATA_PHY_4 |
    386 	    IOMUX_GPR13_SATA_PHY_3 |
    387 	    IOMUX_GPR13_SATA_PHY_2 |
    388 	    IOMUX_GPR13_SATA_PHY_1 |
    389 	    IOMUX_GPR13_SATA_PHY_0);
    390 	/* setting */
    391 	struct {
    392 		const int *array;
    393 		int count;
    394 		int val;
    395 		int def_val;
    396 		int mask;
    397 	} gpr13_sata_phy_settings[] = {
    398 		{ tx_level, __arraycount(tx_level), sc->sc_tx_level,
    399 		  0x11, IOMUX_GPR13_SATA_PHY_2 },
    400 		{ tx_boots, __arraycount(tx_boots), sc->sc_tx_boost,
    401 		  0x09, IOMUX_GPR13_SATA_PHY_3 },
    402 		{ tx_atten, __arraycount(tx_atten), sc->sc_tx_atten,
    403 		  0x04, IOMUX_GPR13_SATA_PHY_4 },
    404 		{ rx_eq, __arraycount(rx_eq), sc->sc_rx_eq,
    405 		  0x05, IOMUX_GPR13_SATA_PHY_8 }
    406 	};
    407 	for (int i = 0; i < __arraycount(gpr13_sata_phy_settings); i++) {
    408 		int val;
    409 		val = imx_ahcisata_search_regval(
    410 			gpr13_sata_phy_settings[i].array,
    411 			gpr13_sata_phy_settings[i].count,
    412 			gpr13_sata_phy_settings[i].val);
    413 		if (val == -1)
    414 			val = gpr13_sata_phy_settings[i].def_val;
    415 		v |= __SHIFTIN(val, gpr13_sata_phy_settings[i].mask);
    416 	}
    417 	v |= __SHIFTIN(0x12, IOMUX_GPR13_SATA_PHY_7);	/* Rx SATA2m */
    418 	v |= __SHIFTIN(3, IOMUX_GPR13_SATA_PHY_6);	/* Rx DPLL mode */
    419 	v |= __SHIFTIN(1, IOMUX_GPR13_SATA_SPEED);	/* 3.0GHz */
    420 	v |= __SHIFTIN(sc->sc_ss, IOMUX_GPR13_SATA_PHY_5);
    421 	v |= __SHIFTIN(1, IOMUX_GPR13_SATA_PHY_1);	/* PLL clock enable */
    422 	bus_space_write_4(sc->sc_iot, sc->sc_gpr_ioh, IOMUX_GPR13, v);
    423 
    424 	/* phy reset */
    425 	if (imx_ahcisata_phy_write(sc, SATA_PHY_CLOCK_RESET,
    426 	    SATA_PHY_CLOCK_RESET_RST) < 0) {
    427 		aprint_error_dev(sc->sc_dev, "cannot reset PHY\n");
    428 		return -1;
    429 	}
    430 
    431 	for (timeout = 50; timeout > 0; --timeout) {
    432 		delay(100);
    433 		pllstat = imx_ahcisata_phy_read(sc, SATA_PHY_LANE0_OUT_STAT);
    434 		if (pllstat < 0) {
    435 			aprint_error_dev(sc->sc_dev,
    436 			    "cannot read LANE0 status\n");
    437 			break;
    438 		}
    439 		if (pllstat & SATA_PHY_LANE0_OUT_STAT_RX_PLL_STATE)
    440 			break;
    441 	}
    442 	if (timeout <= 0)
    443 		return -1;
    444 
    445 	/* Support Staggered Spin-up */
    446 	v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_CAP);
    447 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_CAP, v | SATA_CAP_SSS);
    448 
    449 	/* Ports Implmented. must set 1 */
    450 	v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SATA_PI);
    451 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_PI, v | SATA_PI_PI);
    452 
    453 	/* set 1ms-timer = AHB clock / 1000 */
    454 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SATA_TIMER1MS,
    455 	    clk_get_rate(sc->sc_clk_ahb) / 1000);
    456 
    457 	return 0;
    458 }
    459 
    460 static int
    461 imx_ahcisata_init_clocks(struct imx_ahcisata_softc *sc)
    462 {
    463 	int error;
    464 
    465 	error = clk_enable(sc->sc_clk_sata);
    466 	if (error) {
    467 		aprint_error_dev(sc->sc_dev, "couldn't enable sata: %d\n", error);
    468 		return error;
    469 	}
    470 	error = clk_enable(sc->sc_clk_sata_ref);
    471 	if (error) {
    472 		aprint_error_dev(sc->sc_dev, "couldn't enable sata-ref: %d\n", error);
    473 		return error;
    474 	}
    475 	error = clk_enable(sc->sc_clk_ahb);
    476 	if (error) {
    477 		aprint_error_dev(sc->sc_dev, "couldn't enable anb: %d\n", error);
    478 		return error;
    479 	}
    480 
    481 	return 0;
    482 }
    483