1ef2ee5d0SMichal Meloun /*- 2ef2ee5d0SMichal Meloun * Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org> 3ef2ee5d0SMichal Meloun * All rights reserved. 4ef2ee5d0SMichal Meloun * 5ef2ee5d0SMichal Meloun * Redistribution and use in source and binary forms, with or without 6ef2ee5d0SMichal Meloun * modification, are permitted provided that the following conditions 7ef2ee5d0SMichal Meloun * are met: 8ef2ee5d0SMichal Meloun * 1. Redistributions of source code must retain the above copyright 9ef2ee5d0SMichal Meloun * notice, this list of conditions and the following disclaimer. 10ef2ee5d0SMichal Meloun * 2. Redistributions in binary form must reproduce the above copyright 11ef2ee5d0SMichal Meloun * notice, this list of conditions and the following disclaimer in the 12ef2ee5d0SMichal Meloun * documentation and/or other materials provided with the distribution. 13ef2ee5d0SMichal Meloun * 14ef2ee5d0SMichal Meloun * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15ef2ee5d0SMichal Meloun * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16ef2ee5d0SMichal Meloun * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17ef2ee5d0SMichal Meloun * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18ef2ee5d0SMichal Meloun * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19ef2ee5d0SMichal Meloun * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20ef2ee5d0SMichal Meloun * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21ef2ee5d0SMichal Meloun * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22ef2ee5d0SMichal Meloun * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23ef2ee5d0SMichal Meloun * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24ef2ee5d0SMichal Meloun * SUCH DAMAGE. 25ef2ee5d0SMichal Meloun */ 26ef2ee5d0SMichal Meloun 27ef2ee5d0SMichal Meloun #include <sys/cdefs.h> 28ef2ee5d0SMichal Meloun /* 29ef2ee5d0SMichal Meloun * AHCI driver for Tegra SoCs. 30ef2ee5d0SMichal Meloun */ 31ef2ee5d0SMichal Meloun #include <sys/param.h> 32ef2ee5d0SMichal Meloun #include <sys/module.h> 33ef2ee5d0SMichal Meloun #include <sys/systm.h> 34ef2ee5d0SMichal Meloun #include <sys/bus.h> 35ef2ee5d0SMichal Meloun #include <sys/conf.h> 36ef2ee5d0SMichal Meloun #include <sys/endian.h> 37ef2ee5d0SMichal Meloun #include <sys/kernel.h> 38ef2ee5d0SMichal Meloun #include <sys/lock.h> 39ef2ee5d0SMichal Meloun #include <sys/malloc.h> 40ef2ee5d0SMichal Meloun #include <sys/mutex.h> 41ef2ee5d0SMichal Meloun #include <sys/rman.h> 42ef2ee5d0SMichal Meloun 43ef2ee5d0SMichal Meloun #include <machine/bus.h> 44ef2ee5d0SMichal Meloun #include <machine/resource.h> 45ef2ee5d0SMichal Meloun 46ef2ee5d0SMichal Meloun #include <dev/ahci/ahci.h> 47be82b3a0SEmmanuel Vadot #include <dev/clk/clk.h> 481f469a9fSEmmanuel Vadot #include <dev/hwreset/hwreset.h> 49950a6087SEmmanuel Vadot #include <dev/phy/phy.h> 50b2f0caf1SEmmanuel Vadot #include <dev/regulator/regulator.h> 51ef2ee5d0SMichal Meloun #include <dev/fdt/fdt_pinctrl.h> 52ef2ee5d0SMichal Meloun #include <dev/ofw/ofw_bus.h> 53ef2ee5d0SMichal Meloun #include <dev/ofw/ofw_bus_subr.h> 54ef2ee5d0SMichal Meloun 55ef2ee5d0SMichal Meloun #include <arm/nvidia/tegra_efuse.h> 56ef2ee5d0SMichal Meloun #include <arm/nvidia/tegra_pmc.h> 57ef2ee5d0SMichal Meloun 58ef2ee5d0SMichal Meloun 59ef2ee5d0SMichal Meloun #define SATA_CONFIGURATION 0x180 60b9cbd68dSMichal Meloun #define SATA_CONFIGURATION_CLK_OVERRIDE (1U << 31) 61ef2ee5d0SMichal Meloun #define SATA_CONFIGURATION_EN_FPCI (1 << 0) 62ef2ee5d0SMichal Meloun 63ef2ee5d0SMichal Meloun #define SATA_FPCI_BAR5 0x94 64b9cbd68dSMichal Meloun #define SATA_FPCI_BAR_START(x) (((x) & 0xFFFFFFF) << 4) 65b9cbd68dSMichal Meloun #define SATA_FPCI_BAR_ACCESS_TYPE (1 << 0) 66ef2ee5d0SMichal Meloun 67ef2ee5d0SMichal Meloun #define SATA_INTR_MASK 0x188 68ef2ee5d0SMichal Meloun #define SATA_INTR_MASK_IP_INT_MASK (1 << 16) 69ef2ee5d0SMichal Meloun 70ef2ee5d0SMichal Meloun #define SCFG_OFFSET 0x1000 71ef2ee5d0SMichal Meloun 72ef2ee5d0SMichal Meloun #define T_SATA0_CFG_1 0x04 73ef2ee5d0SMichal Meloun #define T_SATA0_CFG_1_IO_SPACE (1 << 0) 74ef2ee5d0SMichal Meloun #define T_SATA0_CFG_1_MEMORY_SPACE (1 << 1) 75ef2ee5d0SMichal Meloun #define T_SATA0_CFG_1_BUS_MASTER (1 << 2) 76ef2ee5d0SMichal Meloun #define T_SATA0_CFG_1_SERR (1 << 8) 77ef2ee5d0SMichal Meloun 78ef2ee5d0SMichal Meloun #define T_SATA0_CFG_9 0x24 79ef2ee5d0SMichal Meloun #define T_SATA0_CFG_9_BASE_ADDRESS_SHIFT 13 80ef2ee5d0SMichal Meloun 81b9cbd68dSMichal Meloun #define T_SATA0_CFG_35 0x94 82b9cbd68dSMichal Meloun #define T_SATA0_CFG_35_IDP_INDEX_MASK (0x7ff << 2) 83b9cbd68dSMichal Meloun #define T_SATA0_CFG_35_IDP_INDEX (0x2a << 2) 84b9cbd68dSMichal Meloun 85b9cbd68dSMichal Meloun #define T_SATA0_AHCI_IDP1 0x98 86b9cbd68dSMichal Meloun #define T_SATA0_AHCI_IDP1_DATA 0x400040 87b9cbd68dSMichal Meloun 88b9cbd68dSMichal Meloun #define T_SATA0_CFG_PHY_1 0x12c 89b9cbd68dSMichal Meloun #define T_SATA0_CFG_PHY_1_PADS_IDDQ_EN (1 << 23) 90b9cbd68dSMichal Meloun #define T_SATA0_CFG_PHY_1_PAD_PLL_IDDQ_EN (1 << 22) 91b9cbd68dSMichal Meloun 92b9cbd68dSMichal Meloun #define T_SATA0_NVOOB 0x114 93b9cbd68dSMichal Meloun #define T_SATA0_NVOOB_SQUELCH_FILTER_LENGTH_MASK (0x3 << 26) 94b9cbd68dSMichal Meloun #define T_SATA0_NVOOB_SQUELCH_FILTER_LENGTH (0x3 << 26) 95b9cbd68dSMichal Meloun #define T_SATA0_NVOOB_SQUELCH_FILTER_MODE_MASK (0x3 << 24) 96b9cbd68dSMichal Meloun #define T_SATA0_NVOOB_SQUELCH_FILTER_MODE (0x1 << 24) 97b9cbd68dSMichal Meloun #define T_SATA0_NVOOB_COMMA_CNT_MASK (0xff << 16) 98b9cbd68dSMichal Meloun #define T_SATA0_NVOOB_COMMA_CNT (0x07 << 16) 99b9cbd68dSMichal Meloun 100b9cbd68dSMichal Meloun #define T_SATA0_CFG_PHY 0x120 101b9cbd68dSMichal Meloun #define T_SATA0_CFG_PHY_MASK_SQUELCH (1 << 24) 102b9cbd68dSMichal Meloun #define T_SATA0_CFG_PHY_USE_7BIT_ALIGN_DET_FOR_SPD (1 << 11) 103b9cbd68dSMichal Meloun 104b9cbd68dSMichal Meloun #define T_SATA0_CFG2NVOOB_2 0x134 105b9cbd68dSMichal Meloun #define T_SATA0_CFG2NVOOB_2_COMWAKE_IDLE_CNT_LOW_MASK (0x1ff << 18) 106b9cbd68dSMichal Meloun #define T_SATA0_CFG2NVOOB_2_COMWAKE_IDLE_CNT_LOW (0xc << 18) 107b9cbd68dSMichal Meloun 108ef2ee5d0SMichal Meloun #define T_SATA0_AHCI_HBA_CAP_BKDR 0x300 109b9cbd68dSMichal Meloun #define T_SATA0_AHCI_HBA_CAP_BKDR_SNCQ (1 << 30) 110b9cbd68dSMichal Meloun #define T_SATA0_AHCI_HBA_CAP_BKDR_SUPP_PM (1 << 17) 111b9cbd68dSMichal Meloun #define T_SATA0_AHCI_HBA_CAP_BKDR_SALP (1 << 26) 112b9cbd68dSMichal Meloun #define T_SATA0_AHCI_HBA_CAP_BKDR_SLUMBER_ST_CAP (1 << 14) 113b9cbd68dSMichal Meloun #define T_SATA0_AHCI_HBA_CAP_BKDR_PARTIAL_ST_CAP (1 << 13) 114b9cbd68dSMichal Meloun 115ef2ee5d0SMichal Meloun #define T_SATA0_BKDOOR_CC 0x4a4 116b9cbd68dSMichal Meloun #define T_SATA0_BKDOOR_CC_CLASS_CODE_MASK (0xffff << 16) 117b9cbd68dSMichal Meloun #define T_SATA0_BKDOOR_CC_CLASS_CODE (0x0106 << 16) 118b9cbd68dSMichal Meloun #define T_SATA0_BKDOOR_CC_PROG_IF_MASK (0xff << 8) 119b9cbd68dSMichal Meloun #define T_SATA0_BKDOOR_CC_PROG_IF (0x01 << 8) 120b9cbd68dSMichal Meloun 121ef2ee5d0SMichal Meloun #define T_SATA0_CFG_SATA 0x54c 122ef2ee5d0SMichal Meloun #define T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN (1 << 12) 123ef2ee5d0SMichal Meloun 124ef2ee5d0SMichal Meloun #define T_SATA0_CFG_MISC 0x550 125ef2ee5d0SMichal Meloun #define T_SATA0_INDEX 0x680 126ef2ee5d0SMichal Meloun 127ef2ee5d0SMichal Meloun #define T_SATA0_CHX_PHY_CTRL1_GEN1 0x690 128ef2ee5d0SMichal Meloun #define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_MASK 0xff 129ef2ee5d0SMichal Meloun #define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT 8 130ef2ee5d0SMichal Meloun #define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_MASK 0xff 131ef2ee5d0SMichal Meloun #define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT 0 132ef2ee5d0SMichal Meloun 133ef2ee5d0SMichal Meloun #define T_SATA0_CHX_PHY_CTRL1_GEN2 0x694 134ef2ee5d0SMichal Meloun #define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_MASK 0xff 135ef2ee5d0SMichal Meloun #define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_SHIFT 12 136ef2ee5d0SMichal Meloun #define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_MASK 0xff 137ef2ee5d0SMichal Meloun #define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_SHIFT 0 138ef2ee5d0SMichal Meloun 139ef2ee5d0SMichal Meloun #define T_SATA0_CHX_PHY_CTRL2 0x69c 140ef2ee5d0SMichal Meloun #define T_SATA0_CHX_PHY_CTRL2_CDR_CNTL_GEN1 0x23 141ef2ee5d0SMichal Meloun 142ef2ee5d0SMichal Meloun #define T_SATA0_CHX_PHY_CTRL11 0x6d0 143ef2ee5d0SMichal Meloun #define T_SATA0_CHX_PHY_CTRL11_GEN2_RX_EQ (0x2800 << 16) 144ef2ee5d0SMichal Meloun 145b9cbd68dSMichal Meloun #define T_SATA0_CHX_PHY_CTRL17 0x6e8 146b9cbd68dSMichal Meloun #define T_SATA0_CHX_PHY_CTRL18 0x6ec 147b9cbd68dSMichal Meloun #define T_SATA0_CHX_PHY_CTRL20 0x6f4 148b9cbd68dSMichal Meloun #define T_SATA0_CHX_PHY_CTRL21 0x6f8 149b9cbd68dSMichal Meloun 150ef2ee5d0SMichal Meloun #define FUSE_SATA_CALIB 0x124 151ef2ee5d0SMichal Meloun #define FUSE_SATA_CALIB_MASK 0x3 152ef2ee5d0SMichal Meloun 153ef2ee5d0SMichal Meloun #define SATA_AUX_MISC_CNTL 0x1108 154ef2ee5d0SMichal Meloun #define SATA_AUX_PAD_PLL_CTRL_0 0x1120 155ef2ee5d0SMichal Meloun #define SATA_AUX_PAD_PLL_CTRL_1 0x1124 156ef2ee5d0SMichal Meloun #define SATA_AUX_PAD_PLL_CTRL_2 0x1128 157ef2ee5d0SMichal Meloun #define SATA_AUX_PAD_PLL_CTRL_3 0x112c 158ef2ee5d0SMichal Meloun 159ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CCC_PORTS 0x0018 160ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR 0x00A0 161ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_S64A (1 << 31) 162ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_SNCQ (1 << 30) 163ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_SSNTF (1 << 29) 164ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_SMPS (1 << 28) 165ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_SUPP_STG_SPUP (1 << 27) 166ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_SALP (1 << 26) 167ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_SAL (1 << 25) 168ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_SUPP_CLO (1 << 24) 169ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_INTF_SPD_SUPP(x) (((x) & 0xF) << 20) 170ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_SUPP_NONZERO_OFFSET (1 << 19) 171ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_SUPP_AHCI_ONLY (1 << 18) 172ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_SUPP_PM (1 << 17) 173ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_FIS_SWITCHING (1 << 16) 174ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_PIO_MULT_DRQ_BLK (1 << 15) 175ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_SLUMBER_ST_CAP (1 << 14) 176ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_PARTIAL_ST_CAP (1 << 13) 177ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_NUM_CMD_SLOTS(x) (((x) & 0x1F) << 8) 178ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_CMD_CMPL_COALESING (1 << 7) 179ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_ENCL_MGMT_SUPP (1 << 6) 180ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_EXT_SATA (1 << 5) 181ef2ee5d0SMichal Meloun #define T_AHCI_HBA_CAP_BKDR_NUM_PORTS(x) (((x) & 0xF) << 0) 182ef2ee5d0SMichal Meloun 183ef2ee5d0SMichal Meloun #define T_AHCI_PORT_BKDR 0x0170 184ef2ee5d0SMichal Meloun 185ef2ee5d0SMichal Meloun #define T_AHCI_PORT_BKDR_PXDEVSLP_DETO_OVERRIDE_VAL(x) (((x) & 0xFF) << 24) 186ef2ee5d0SMichal Meloun #define T_AHCI_PORT_BKDR_PXDEVSLP_MDAT_OVERRIDE_VAL(x) (((x) & 0x1F) << 16) 187ef2ee5d0SMichal Meloun #define T_AHCI_PORT_BKDR_PXDEVSLP_DETO_OVERRIDE (1 << 15) 188ef2ee5d0SMichal Meloun #define T_AHCI_PORT_BKDR_PXDEVSLP_MDAT_OVERRIDE (1 << 14) 189ef2ee5d0SMichal Meloun #define T_AHCI_PORT_BKDR_PXDEVSLP_DM(x) (((x) & 0xF) << 10) 190ef2ee5d0SMichal Meloun #define T_AHCI_PORT_BKDR_PORT_UNCONNECTED (1 << 9) 191ef2ee5d0SMichal Meloun #define T_AHCI_PORT_BKDR_CLK_CLAMP_CTRL_CLAMP_THIS_CH (1 << 8) 192ef2ee5d0SMichal Meloun #define T_AHCI_PORT_BKDR_CLK_CLAMP_CTRL_TXRXCLK_UNCLAMP (1 << 7) 193ef2ee5d0SMichal Meloun #define T_AHCI_PORT_BKDR_CLK_CLAMP_CTRL_TXRXCLK_CLAMP (1 << 6) 194ef2ee5d0SMichal Meloun #define T_AHCI_PORT_BKDR_CLK_CLAMP_CTRL_DEVCLK_UNCLAMP (1 << 5) 195ef2ee5d0SMichal Meloun #define T_AHCI_PORT_BKDR_CLK_CLAMP_CTRL_DEVCLK_CLAMP (1 << 4) 196ef2ee5d0SMichal Meloun #define T_AHCI_PORT_BKDR_HOTPLUG_CAP (1 << 3) 197ef2ee5d0SMichal Meloun #define T_AHCI_PORT_BKDR_MECH_SWITCH (1 << 2) 198ef2ee5d0SMichal Meloun #define T_AHCI_PORT_BKDR_COLD_PRSN_DET (1 << 1) 199ef2ee5d0SMichal Meloun #define T_AHCI_PORT_BKDR_EXT_SATA_SUPP (1 << 0) 200ef2ee5d0SMichal Meloun 201b9cbd68dSMichal Meloun /* AUX registers */ 202b9cbd68dSMichal Meloun #define SATA_AUX_MISC_CNTL_1 0x008 203b9cbd68dSMichal Meloun #define SATA_AUX_MISC_CNTL_1_DEVSLP_OVERRIDE (1 << 17) 204b9cbd68dSMichal Meloun #define SATA_AUX_MISC_CNTL_1_SDS_SUPPORT (1 << 13) 205b9cbd68dSMichal Meloun #define SATA_AUX_MISC_CNTL_1_DESO_SUPPORT (1 << 15) 206b9cbd68dSMichal Meloun 207b9cbd68dSMichal Meloun #define AHCI_WR4(_sc, _r, _v) bus_write_4((_sc)->ctlr.r_mem, (_r), (_v)) 208b9cbd68dSMichal Meloun #define AHCI_RD4(_sc, _r) bus_read_4((_sc)->ctlr.r_mem, (_r)) 209b9cbd68dSMichal Meloun #define SATA_WR4(_sc, _r, _v) bus_write_4((_sc)->sata_mem, (_r), (_v)) 210b9cbd68dSMichal Meloun #define SATA_RD4(_sc, _r) bus_read_4((_sc)->sata_mem, (_r)) 211b9cbd68dSMichal Meloun 212b9cbd68dSMichal Meloun struct sata_pad_calibration { 213b9cbd68dSMichal Meloun uint32_t gen1_tx_amp; 214b9cbd68dSMichal Meloun uint32_t gen1_tx_peak; 215b9cbd68dSMichal Meloun uint32_t gen2_tx_amp; 216b9cbd68dSMichal Meloun uint32_t gen2_tx_peak; 217b9cbd68dSMichal Meloun }; 218b9cbd68dSMichal Meloun 219b9cbd68dSMichal Meloun static const struct sata_pad_calibration tegra124_pad_calibration[] = { 220b9cbd68dSMichal Meloun {0x18, 0x04, 0x18, 0x0a}, 221b9cbd68dSMichal Meloun {0x0e, 0x04, 0x14, 0x0a}, 222b9cbd68dSMichal Meloun {0x0e, 0x07, 0x1a, 0x0e}, 223b9cbd68dSMichal Meloun {0x14, 0x0e, 0x1a, 0x0e}, 224b9cbd68dSMichal Meloun }; 225b9cbd68dSMichal Meloun 226b9cbd68dSMichal Meloun struct ahci_soc; 227b9cbd68dSMichal Meloun struct tegra_ahci_sc { 228b9cbd68dSMichal Meloun struct ahci_controller ctlr; /* Must be first */ 229b9cbd68dSMichal Meloun device_t dev; 230b9cbd68dSMichal Meloun struct ahci_soc *soc; 231b9cbd68dSMichal Meloun struct resource *sata_mem; 232b9cbd68dSMichal Meloun struct resource *aux_mem; 233b9cbd68dSMichal Meloun clk_t clk_sata; 234b9cbd68dSMichal Meloun clk_t clk_sata_oob; 235b9cbd68dSMichal Meloun clk_t clk_pll_e; 236b9cbd68dSMichal Meloun clk_t clk_cml; 237b9cbd68dSMichal Meloun hwreset_t hwreset_sata; 238b9cbd68dSMichal Meloun hwreset_t hwreset_sata_oob; 239b9cbd68dSMichal Meloun hwreset_t hwreset_sata_cold; 240b9cbd68dSMichal Meloun regulator_t regulators[16]; /* Safe maximum */ 241b9cbd68dSMichal Meloun phy_t phy; 242b9cbd68dSMichal Meloun }; 243b9cbd68dSMichal Meloun 244b9cbd68dSMichal Meloun struct ahci_soc { 245b9cbd68dSMichal Meloun char **regulator_names; 246b9cbd68dSMichal Meloun int (*init)(struct tegra_ahci_sc *sc); 247b9cbd68dSMichal Meloun }; 248b9cbd68dSMichal Meloun 249b9cbd68dSMichal Meloun /* Tegra 124 config. */ 250b9cbd68dSMichal Meloun static char *tegra124_reg_names[] = { 251b9cbd68dSMichal Meloun "hvdd-supply", 252b9cbd68dSMichal Meloun "vddio-supply", 253b9cbd68dSMichal Meloun "avdd-supply", 254b9cbd68dSMichal Meloun "target-5v-supply", 255b9cbd68dSMichal Meloun "target-12v-supply", 256b9cbd68dSMichal Meloun NULL 257b9cbd68dSMichal Meloun }; 258b9cbd68dSMichal Meloun 259b9cbd68dSMichal Meloun static int tegra124_ahci_init(struct tegra_ahci_sc *sc); 260b9cbd68dSMichal Meloun static struct ahci_soc tegra124_soc = { 261b9cbd68dSMichal Meloun .regulator_names = tegra124_reg_names, 262b9cbd68dSMichal Meloun .init = tegra124_ahci_init, 263b9cbd68dSMichal Meloun }; 264b9cbd68dSMichal Meloun 265b9cbd68dSMichal Meloun /* Tegra 210 config. */ 266b9cbd68dSMichal Meloun static char *tegra210_reg_names[] = { 267b9cbd68dSMichal Meloun NULL 268b9cbd68dSMichal Meloun }; 269b9cbd68dSMichal Meloun 270b9cbd68dSMichal Meloun static struct ahci_soc tegra210_soc = { 271b9cbd68dSMichal Meloun .regulator_names = tegra210_reg_names, 272b9cbd68dSMichal Meloun }; 273b9cbd68dSMichal Meloun 274b9cbd68dSMichal Meloun 275b9cbd68dSMichal Meloun static struct ofw_compat_data compat_data[] = { 276b9cbd68dSMichal Meloun {"nvidia,tegra124-ahci", (uintptr_t)&tegra124_soc}, 277b9cbd68dSMichal Meloun {"nvidia,tegra210-ahci", (uintptr_t)&tegra210_soc}, 278b9cbd68dSMichal Meloun {NULL, 0} 279b9cbd68dSMichal Meloun }; 280b9cbd68dSMichal Meloun 281ef2ee5d0SMichal Meloun static int 282ef2ee5d0SMichal Meloun get_fdt_resources(struct tegra_ahci_sc *sc, phandle_t node) 283ef2ee5d0SMichal Meloun { 284b9cbd68dSMichal Meloun int i, rv; 285ef2ee5d0SMichal Meloun 286b9cbd68dSMichal Meloun /* Regulators. */ 287b9cbd68dSMichal Meloun for (i = 0; sc->soc->regulator_names[i] != NULL; i++) { 288b9cbd68dSMichal Meloun if (i >= nitems(sc->regulators)) { 289b9cbd68dSMichal Meloun device_printf(sc->dev, 290b9cbd68dSMichal Meloun "Too many regulators present in DT.\n"); 291b9cbd68dSMichal Meloun return (EOVERFLOW); 292b9cbd68dSMichal Meloun } 293b9cbd68dSMichal Meloun rv = regulator_get_by_ofw_property(sc->dev, 0, 294b9cbd68dSMichal Meloun sc->soc->regulator_names[i], sc->regulators + i); 295ef2ee5d0SMichal Meloun if (rv != 0) { 296b9cbd68dSMichal Meloun device_printf(sc->dev, 297b9cbd68dSMichal Meloun "Cannot get '%s' regulator\n", 298b9cbd68dSMichal Meloun sc->soc->regulator_names[i]); 299ef2ee5d0SMichal Meloun return (ENXIO); 300ef2ee5d0SMichal Meloun } 301ef2ee5d0SMichal Meloun } 302ef2ee5d0SMichal Meloun 303b9cbd68dSMichal Meloun /* Resets. */ 304dac93553SMichal Meloun rv = hwreset_get_by_ofw_name(sc->dev, 0, "sata", &sc->hwreset_sata ); 305ef2ee5d0SMichal Meloun if (rv != 0) { 306ef2ee5d0SMichal Meloun device_printf(sc->dev, "Cannot get 'sata' reset\n"); 307ef2ee5d0SMichal Meloun return (ENXIO); 308ef2ee5d0SMichal Meloun } 309dac93553SMichal Meloun rv = hwreset_get_by_ofw_name(sc->dev, 0, "sata-oob", 310ef2ee5d0SMichal Meloun &sc->hwreset_sata_oob); 311ef2ee5d0SMichal Meloun if (rv != 0) { 312ef2ee5d0SMichal Meloun device_printf(sc->dev, "Cannot get 'sata oob' reset\n"); 313ef2ee5d0SMichal Meloun return (ENXIO); 314ef2ee5d0SMichal Meloun } 315dac93553SMichal Meloun rv = hwreset_get_by_ofw_name(sc->dev, 0, "sata-cold", 316ef2ee5d0SMichal Meloun &sc->hwreset_sata_cold); 317ef2ee5d0SMichal Meloun if (rv != 0) { 318ef2ee5d0SMichal Meloun device_printf(sc->dev, "Cannot get 'sata cold' reset\n"); 319ef2ee5d0SMichal Meloun return (ENXIO); 320ef2ee5d0SMichal Meloun } 321ef2ee5d0SMichal Meloun 322b9cbd68dSMichal Meloun /* Phy */ 32323ea1f2bSOleksandr Tymoshenko rv = phy_get_by_ofw_name(sc->dev, 0, "sata-0", &sc->phy); 324ef2ee5d0SMichal Meloun if (rv != 0) { 325b9cbd68dSMichal Meloun rv = phy_get_by_ofw_idx(sc->dev, 0, 0, &sc->phy); 326b9cbd68dSMichal Meloun if (rv != 0) { 327ef2ee5d0SMichal Meloun device_printf(sc->dev, "Cannot get 'sata' phy\n"); 328ef2ee5d0SMichal Meloun return (ENXIO); 329ef2ee5d0SMichal Meloun } 330b9cbd68dSMichal Meloun } 331ef2ee5d0SMichal Meloun 332b9cbd68dSMichal Meloun /* Clocks. */ 333dac93553SMichal Meloun rv = clk_get_by_ofw_name(sc->dev, 0, "sata", &sc->clk_sata); 334ef2ee5d0SMichal Meloun if (rv != 0) { 335ef2ee5d0SMichal Meloun device_printf(sc->dev, "Cannot get 'sata' clock\n"); 336ef2ee5d0SMichal Meloun return (ENXIO); 337ef2ee5d0SMichal Meloun } 338dac93553SMichal Meloun rv = clk_get_by_ofw_name(sc->dev, 0, "sata-oob", &sc->clk_sata_oob); 339ef2ee5d0SMichal Meloun if (rv != 0) { 340ef2ee5d0SMichal Meloun device_printf(sc->dev, "Cannot get 'sata oob' clock\n"); 341ef2ee5d0SMichal Meloun return (ENXIO); 342ef2ee5d0SMichal Meloun } 343b9cbd68dSMichal Meloun /* These are optional */ 344dac93553SMichal Meloun rv = clk_get_by_ofw_name(sc->dev, 0, "cml1", &sc->clk_cml); 345b9cbd68dSMichal Meloun if (rv != 0) 346b9cbd68dSMichal Meloun sc->clk_cml = NULL; 347b9cbd68dSMichal Meloun 348dac93553SMichal Meloun rv = clk_get_by_ofw_name(sc->dev, 0, "pll_e", &sc->clk_pll_e); 349b9cbd68dSMichal Meloun if (rv != 0) 350b9cbd68dSMichal Meloun sc->clk_pll_e = NULL; 351ef2ee5d0SMichal Meloun return (0); 352ef2ee5d0SMichal Meloun } 353ef2ee5d0SMichal Meloun 354ef2ee5d0SMichal Meloun static int 355ef2ee5d0SMichal Meloun enable_fdt_resources(struct tegra_ahci_sc *sc) 356ef2ee5d0SMichal Meloun { 357b9cbd68dSMichal Meloun int i, rv; 358ef2ee5d0SMichal Meloun 359b9cbd68dSMichal Meloun /* Enable regulators. */ 360b9cbd68dSMichal Meloun for (i = 0; i < nitems(sc->regulators); i++) { 361b9cbd68dSMichal Meloun if (sc->regulators[i] == NULL) 362b9cbd68dSMichal Meloun continue; 363b9cbd68dSMichal Meloun rv = regulator_enable(sc->regulators[i]); 364ef2ee5d0SMichal Meloun if (rv != 0) { 365ef2ee5d0SMichal Meloun device_printf(sc->dev, 366b9cbd68dSMichal Meloun "Cannot enable '%s' regulator\n", 367b9cbd68dSMichal Meloun sc->soc->regulator_names[i]); 368ef2ee5d0SMichal Meloun return (rv); 369ef2ee5d0SMichal Meloun } 370ef2ee5d0SMichal Meloun } 371ef2ee5d0SMichal Meloun 372ef2ee5d0SMichal Meloun /* Stop clocks */ 373ef2ee5d0SMichal Meloun clk_stop(sc->clk_sata); 374ef2ee5d0SMichal Meloun clk_stop(sc->clk_sata_oob); 375ef2ee5d0SMichal Meloun tegra_powergate_power_off(TEGRA_POWERGATE_SAX); 376ef2ee5d0SMichal Meloun 377ef2ee5d0SMichal Meloun rv = hwreset_assert(sc->hwreset_sata); 378ef2ee5d0SMichal Meloun if (rv != 0) { 379ef2ee5d0SMichal Meloun device_printf(sc->dev, "Cannot assert 'sata' reset\n"); 380ef2ee5d0SMichal Meloun return (rv); 381ef2ee5d0SMichal Meloun } 382ef2ee5d0SMichal Meloun rv = hwreset_assert(sc->hwreset_sata_oob); 383ef2ee5d0SMichal Meloun if (rv != 0) { 384ef2ee5d0SMichal Meloun device_printf(sc->dev, "Cannot assert 'sata oob' reset\n"); 385ef2ee5d0SMichal Meloun return (rv); 386ef2ee5d0SMichal Meloun } 387ef2ee5d0SMichal Meloun 388ef2ee5d0SMichal Meloun rv = hwreset_assert(sc->hwreset_sata_cold); 389ef2ee5d0SMichal Meloun if (rv != 0) { 390ef2ee5d0SMichal Meloun device_printf(sc->dev, "Cannot assert 'sata cold' reset\n"); 391ef2ee5d0SMichal Meloun return (rv); 392ef2ee5d0SMichal Meloun } 393ef2ee5d0SMichal Meloun rv = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_SAX, 394ef2ee5d0SMichal Meloun sc->clk_sata, sc->hwreset_sata); 395ef2ee5d0SMichal Meloun if (rv != 0) { 396ef2ee5d0SMichal Meloun device_printf(sc->dev, "Cannot enable 'SAX' powergate\n"); 397ef2ee5d0SMichal Meloun return (rv); 398ef2ee5d0SMichal Meloun } 399ef2ee5d0SMichal Meloun 400ef2ee5d0SMichal Meloun rv = clk_enable(sc->clk_sata_oob); 401ef2ee5d0SMichal Meloun if (rv != 0) { 402ef2ee5d0SMichal Meloun device_printf(sc->dev, "Cannot enable 'sata oob' clock\n"); 403ef2ee5d0SMichal Meloun return (rv); 404ef2ee5d0SMichal Meloun } 405b9cbd68dSMichal Meloun if (sc->clk_cml != NULL) { 406ef2ee5d0SMichal Meloun rv = clk_enable(sc->clk_cml); 407ef2ee5d0SMichal Meloun if (rv != 0) { 408ef2ee5d0SMichal Meloun device_printf(sc->dev, "Cannot enable 'cml' clock\n"); 409ef2ee5d0SMichal Meloun return (rv); 410ef2ee5d0SMichal Meloun } 411b9cbd68dSMichal Meloun } 412b9cbd68dSMichal Meloun if (sc->clk_pll_e != NULL) { 413ef2ee5d0SMichal Meloun rv = clk_enable(sc->clk_pll_e); 414ef2ee5d0SMichal Meloun if (rv != 0) { 415ef2ee5d0SMichal Meloun device_printf(sc->dev, "Cannot enable 'pll e' clock\n"); 416ef2ee5d0SMichal Meloun return (rv); 417ef2ee5d0SMichal Meloun } 418b9cbd68dSMichal Meloun } 419ef2ee5d0SMichal Meloun 420ef2ee5d0SMichal Meloun rv = hwreset_deassert(sc->hwreset_sata_cold); 421ef2ee5d0SMichal Meloun if (rv != 0) { 422ef2ee5d0SMichal Meloun device_printf(sc->dev, "Cannot unreset 'sata cold' reset\n"); 423ef2ee5d0SMichal Meloun return (rv); 424ef2ee5d0SMichal Meloun } 425ef2ee5d0SMichal Meloun rv = hwreset_deassert(sc->hwreset_sata_oob); 426ef2ee5d0SMichal Meloun if (rv != 0) { 427ef2ee5d0SMichal Meloun device_printf(sc->dev, "Cannot unreset 'sata oob' reset\n"); 428ef2ee5d0SMichal Meloun return (rv); 429ef2ee5d0SMichal Meloun } 430ef2ee5d0SMichal Meloun 431f8759facSMichal Meloun rv = phy_enable(sc->phy); 432ef2ee5d0SMichal Meloun if (rv != 0) { 433ef2ee5d0SMichal Meloun device_printf(sc->dev, "Cannot enable SATA phy\n"); 434ef2ee5d0SMichal Meloun return (rv); 435ef2ee5d0SMichal Meloun } 436ef2ee5d0SMichal Meloun 437ef2ee5d0SMichal Meloun return (0); 438ef2ee5d0SMichal Meloun } 439ef2ee5d0SMichal Meloun 440ef2ee5d0SMichal Meloun static int 441b9cbd68dSMichal Meloun tegra124_ahci_init(struct tegra_ahci_sc *sc) 442ef2ee5d0SMichal Meloun { 443ef2ee5d0SMichal Meloun uint32_t val; 444ef2ee5d0SMichal Meloun const struct sata_pad_calibration *calib; 445ef2ee5d0SMichal Meloun 446ef2ee5d0SMichal Meloun /* Pad calibration. */ 447ef2ee5d0SMichal Meloun val = tegra_fuse_read_4(FUSE_SATA_CALIB); 448ef2ee5d0SMichal Meloun calib = tegra124_pad_calibration + (val & FUSE_SATA_CALIB_MASK); 449ef2ee5d0SMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_INDEX, 1); 450ef2ee5d0SMichal Meloun 451ef2ee5d0SMichal Meloun val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN1); 452ef2ee5d0SMichal Meloun val &= ~(T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_MASK << 453ef2ee5d0SMichal Meloun T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT); 454ef2ee5d0SMichal Meloun val &= ~(T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_MASK << 455ef2ee5d0SMichal Meloun T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT); 456ef2ee5d0SMichal Meloun val |= calib->gen1_tx_amp << T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT; 457ef2ee5d0SMichal Meloun val |= calib->gen1_tx_peak << T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT; 458ef2ee5d0SMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN1, val); 459ef2ee5d0SMichal Meloun 460ef2ee5d0SMichal Meloun val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN2); 461ef2ee5d0SMichal Meloun val &= ~(T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_MASK << 462ef2ee5d0SMichal Meloun T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_SHIFT); 463ef2ee5d0SMichal Meloun val &= ~(T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_MASK << 464ef2ee5d0SMichal Meloun T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_SHIFT); 465ef2ee5d0SMichal Meloun val |= calib->gen2_tx_amp << T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_SHIFT; 466ef2ee5d0SMichal Meloun val |= calib->gen2_tx_peak << T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_SHIFT; 467ef2ee5d0SMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN2, val); 468ef2ee5d0SMichal Meloun 469ef2ee5d0SMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL11, 470ef2ee5d0SMichal Meloun T_SATA0_CHX_PHY_CTRL11_GEN2_RX_EQ); 471ef2ee5d0SMichal Meloun 472ef2ee5d0SMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL2, 473ef2ee5d0SMichal Meloun T_SATA0_CHX_PHY_CTRL2_CDR_CNTL_GEN1); 474ef2ee5d0SMichal Meloun 475ef2ee5d0SMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_INDEX, 0); 476ef2ee5d0SMichal Meloun 477b9cbd68dSMichal Meloun return (0); 478b9cbd68dSMichal Meloun } 479b9cbd68dSMichal Meloun 480b9cbd68dSMichal Meloun static int 481b9cbd68dSMichal Meloun tegra_ahci_ctrl_init(struct tegra_ahci_sc *sc) 482b9cbd68dSMichal Meloun { 483b9cbd68dSMichal Meloun uint32_t val; 484b9cbd68dSMichal Meloun int rv; 485b9cbd68dSMichal Meloun 486b9cbd68dSMichal Meloun /* Enable SATA MMIO. */ 487b9cbd68dSMichal Meloun val = SATA_RD4(sc, SATA_FPCI_BAR5); 488b9cbd68dSMichal Meloun val &= ~SATA_FPCI_BAR_START(~0); 489b9cbd68dSMichal Meloun val |= SATA_FPCI_BAR_START(0x10000); 490b9cbd68dSMichal Meloun val |= SATA_FPCI_BAR_ACCESS_TYPE; 491b9cbd68dSMichal Meloun SATA_WR4(sc, SATA_FPCI_BAR5, val); 492b9cbd68dSMichal Meloun 493b9cbd68dSMichal Meloun /* Enable FPCI access */ 494b9cbd68dSMichal Meloun val = SATA_RD4(sc, SATA_CONFIGURATION); 495b9cbd68dSMichal Meloun val |= SATA_CONFIGURATION_EN_FPCI; 496b9cbd68dSMichal Meloun SATA_WR4(sc, SATA_CONFIGURATION, val); 497b9cbd68dSMichal Meloun 498b9cbd68dSMichal Meloun /* Recommended electrical settings for phy */ 499b9cbd68dSMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL17, 0x55010000); 500b9cbd68dSMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL18, 0x55010000); 501b9cbd68dSMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL20, 0x1); 502b9cbd68dSMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL21, 0x1); 503b9cbd68dSMichal Meloun 504b9cbd68dSMichal Meloun /* SQUELCH and Gen3 */ 505b9cbd68dSMichal Meloun val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_PHY); 506b9cbd68dSMichal Meloun val |= T_SATA0_CFG_PHY_MASK_SQUELCH; 507b9cbd68dSMichal Meloun val &= ~T_SATA0_CFG_PHY_USE_7BIT_ALIGN_DET_FOR_SPD; 508b9cbd68dSMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_PHY, val); 509b9cbd68dSMichal Meloun 510b9cbd68dSMichal Meloun val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_NVOOB); 511b9cbd68dSMichal Meloun val &= ~T_SATA0_NVOOB_COMMA_CNT_MASK; 512b9cbd68dSMichal Meloun val &= ~T_SATA0_NVOOB_SQUELCH_FILTER_LENGTH_MASK; 513b9cbd68dSMichal Meloun val &= ~T_SATA0_NVOOB_SQUELCH_FILTER_MODE_MASK; 514b9cbd68dSMichal Meloun val |= T_SATA0_NVOOB_COMMA_CNT; 515b9cbd68dSMichal Meloun val |= T_SATA0_NVOOB_SQUELCH_FILTER_LENGTH; 516b9cbd68dSMichal Meloun val |= T_SATA0_NVOOB_SQUELCH_FILTER_MODE; 517b9cbd68dSMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_NVOOB, val); 518b9cbd68dSMichal Meloun 519b9cbd68dSMichal Meloun /* Setup COMWAKE_IDLE_CNT */ 520b9cbd68dSMichal Meloun val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG2NVOOB_2); 521b9cbd68dSMichal Meloun val &= ~T_SATA0_CFG2NVOOB_2_COMWAKE_IDLE_CNT_LOW_MASK; 522b9cbd68dSMichal Meloun val |= T_SATA0_CFG2NVOOB_2_COMWAKE_IDLE_CNT_LOW; 523b9cbd68dSMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG2NVOOB_2, val); 524b9cbd68dSMichal Meloun 525b9cbd68dSMichal Meloun if (sc->soc->init != NULL) { 526b9cbd68dSMichal Meloun rv = sc->soc->init(sc); 527b9cbd68dSMichal Meloun if (rv != 0) { 528b9cbd68dSMichal Meloun device_printf(sc->dev, 529b9cbd68dSMichal Meloun "SOC specific intialization failed: %d\n", rv); 530b9cbd68dSMichal Meloun return (rv); 531b9cbd68dSMichal Meloun } 532b9cbd68dSMichal Meloun } 533b9cbd68dSMichal Meloun 534b9cbd68dSMichal Meloun /* Enable backdoor programming. */ 535ef2ee5d0SMichal Meloun val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_SATA); 536ef2ee5d0SMichal Meloun val |= T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN; 537ef2ee5d0SMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_SATA, val); 538ef2ee5d0SMichal Meloun 539b9cbd68dSMichal Meloun /* Set device class and interface */ 540b9cbd68dSMichal Meloun val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_BKDOOR_CC); 541b9cbd68dSMichal Meloun val &= ~T_SATA0_BKDOOR_CC_CLASS_CODE_MASK; 542b9cbd68dSMichal Meloun val &= ~T_SATA0_BKDOOR_CC_PROG_IF_MASK; 543b9cbd68dSMichal Meloun val |= T_SATA0_BKDOOR_CC_CLASS_CODE; 544b9cbd68dSMichal Meloun val |= T_SATA0_BKDOOR_CC_PROG_IF; 545b9cbd68dSMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_BKDOOR_CC, val); 546ef2ee5d0SMichal Meloun 547b9cbd68dSMichal Meloun /* Enable LPM capabilities */ 548b9cbd68dSMichal Meloun val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_AHCI_HBA_CAP_BKDR); 549b9cbd68dSMichal Meloun val |= T_SATA0_AHCI_HBA_CAP_BKDR_PARTIAL_ST_CAP; 550b9cbd68dSMichal Meloun val |= T_SATA0_AHCI_HBA_CAP_BKDR_SLUMBER_ST_CAP; 551b9cbd68dSMichal Meloun val |= T_SATA0_AHCI_HBA_CAP_BKDR_SALP; 552b9cbd68dSMichal Meloun val |= T_SATA0_AHCI_HBA_CAP_BKDR_SUPP_PM; 553b9cbd68dSMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_AHCI_HBA_CAP_BKDR, val); 554b9cbd68dSMichal Meloun 555b9cbd68dSMichal Meloun /* Disable backdoor programming. */ 556ef2ee5d0SMichal Meloun val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_SATA); 557ef2ee5d0SMichal Meloun val &= ~T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN; 558ef2ee5d0SMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_SATA, val); 559ef2ee5d0SMichal Meloun 560b9cbd68dSMichal Meloun /* SATA Second Level Clock Gating */ 561b9cbd68dSMichal Meloun val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_35); 562b9cbd68dSMichal Meloun val &= ~T_SATA0_CFG_35_IDP_INDEX_MASK; 563b9cbd68dSMichal Meloun val |= T_SATA0_CFG_35_IDP_INDEX; 564b9cbd68dSMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_35, val); 565b9cbd68dSMichal Meloun 566b9cbd68dSMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_AHCI_IDP1, 0x400040); 567b9cbd68dSMichal Meloun 568b9cbd68dSMichal Meloun val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_PHY_1); 569b9cbd68dSMichal Meloun val |= T_SATA0_CFG_PHY_1_PADS_IDDQ_EN; 570b9cbd68dSMichal Meloun val |= T_SATA0_CFG_PHY_1_PAD_PLL_IDDQ_EN; 571b9cbd68dSMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_PHY_1, val); 572b9cbd68dSMichal Meloun 573b9cbd68dSMichal Meloun /* 574b9cbd68dSMichal Meloun * Indicate Sata only has the capability to enter DevSleep 575b9cbd68dSMichal Meloun * from slumber link. 576b9cbd68dSMichal Meloun */ 577b9cbd68dSMichal Meloun if (sc->aux_mem != NULL) { 578b9cbd68dSMichal Meloun val = bus_read_4(sc->aux_mem, SATA_AUX_MISC_CNTL_1); 579b9cbd68dSMichal Meloun val |= SATA_AUX_MISC_CNTL_1_DESO_SUPPORT; 580b9cbd68dSMichal Meloun bus_write_4(sc->aux_mem, SATA_AUX_MISC_CNTL_1, val); 581b9cbd68dSMichal Meloun } 582b9cbd68dSMichal Meloun 583b9cbd68dSMichal Meloun /* Enable IPFS Clock Gating */ 584b9cbd68dSMichal Meloun val = SATA_RD4(sc, SCFG_OFFSET + SATA_CONFIGURATION); 585b9cbd68dSMichal Meloun val &= ~SATA_CONFIGURATION_CLK_OVERRIDE; 586b9cbd68dSMichal Meloun SATA_WR4(sc, SCFG_OFFSET + SATA_CONFIGURATION, val); 587b9cbd68dSMichal Meloun 588b9cbd68dSMichal Meloun 589ef2ee5d0SMichal Meloun /* Enable IO & memory access, bus master mode */ 590ef2ee5d0SMichal Meloun val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_1); 591ef2ee5d0SMichal Meloun val |= T_SATA0_CFG_1_IO_SPACE; 592ef2ee5d0SMichal Meloun val |= T_SATA0_CFG_1_MEMORY_SPACE; 593ef2ee5d0SMichal Meloun val |= T_SATA0_CFG_1_BUS_MASTER; 594ef2ee5d0SMichal Meloun val |= T_SATA0_CFG_1_SERR; 595ef2ee5d0SMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_1, val); 596ef2ee5d0SMichal Meloun 597ef2ee5d0SMichal Meloun /* AHCI bar */ 598ef2ee5d0SMichal Meloun SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_9, 599ef2ee5d0SMichal Meloun 0x08000 << T_SATA0_CFG_9_BASE_ADDRESS_SHIFT); 600ef2ee5d0SMichal Meloun 601ef2ee5d0SMichal Meloun /* Unmask interrupts. */ 602ef2ee5d0SMichal Meloun val = SATA_RD4(sc, SATA_INTR_MASK); 603ef2ee5d0SMichal Meloun val |= SATA_INTR_MASK_IP_INT_MASK; 604ef2ee5d0SMichal Meloun SATA_WR4(sc, SATA_INTR_MASK, val); 605ef2ee5d0SMichal Meloun 606ef2ee5d0SMichal Meloun return (0); 607ef2ee5d0SMichal Meloun } 608ef2ee5d0SMichal Meloun 609ef2ee5d0SMichal Meloun static int 610ef2ee5d0SMichal Meloun tegra_ahci_ctlr_reset(device_t dev) 611ef2ee5d0SMichal Meloun { 612ef2ee5d0SMichal Meloun struct tegra_ahci_sc *sc; 613ef2ee5d0SMichal Meloun int rv; 614ef2ee5d0SMichal Meloun uint32_t reg; 615ef2ee5d0SMichal Meloun 616ef2ee5d0SMichal Meloun sc = device_get_softc(dev); 617ef2ee5d0SMichal Meloun rv = ahci_ctlr_reset(dev); 618ef2ee5d0SMichal Meloun if (rv != 0) 619ef2ee5d0SMichal Meloun return (0); 620ef2ee5d0SMichal Meloun AHCI_WR4(sc, T_AHCI_HBA_CCC_PORTS, 1); 621ef2ee5d0SMichal Meloun 622ef2ee5d0SMichal Meloun /* Overwrite AHCI capabilites. */ 623ef2ee5d0SMichal Meloun reg = AHCI_RD4(sc, T_AHCI_HBA_CAP_BKDR); 624ef2ee5d0SMichal Meloun reg &= ~T_AHCI_HBA_CAP_BKDR_NUM_PORTS(~0); 625ef2ee5d0SMichal Meloun reg |= T_AHCI_HBA_CAP_BKDR_NUM_PORTS(0); 626ef2ee5d0SMichal Meloun reg |= T_AHCI_HBA_CAP_BKDR_EXT_SATA; 627ef2ee5d0SMichal Meloun reg |= T_AHCI_HBA_CAP_BKDR_CMD_CMPL_COALESING; 628ef2ee5d0SMichal Meloun reg |= T_AHCI_HBA_CAP_BKDR_FIS_SWITCHING; 629ef2ee5d0SMichal Meloun reg |= T_AHCI_HBA_CAP_BKDR_SUPP_PM; 630ef2ee5d0SMichal Meloun reg |= T_AHCI_HBA_CAP_BKDR_SUPP_CLO; 631ef2ee5d0SMichal Meloun reg |= T_AHCI_HBA_CAP_BKDR_SUPP_STG_SPUP; 632ef2ee5d0SMichal Meloun AHCI_WR4(sc, T_AHCI_HBA_CAP_BKDR, reg); 633ef2ee5d0SMichal Meloun 634ef2ee5d0SMichal Meloun /* Overwrite AHCI portcapabilites. */ 635ef2ee5d0SMichal Meloun reg = AHCI_RD4(sc, T_AHCI_PORT_BKDR); 636ef2ee5d0SMichal Meloun reg |= T_AHCI_PORT_BKDR_COLD_PRSN_DET; 637ef2ee5d0SMichal Meloun reg |= T_AHCI_PORT_BKDR_HOTPLUG_CAP; 638ef2ee5d0SMichal Meloun reg |= T_AHCI_PORT_BKDR_EXT_SATA_SUPP; 639ef2ee5d0SMichal Meloun AHCI_WR4(sc, T_AHCI_PORT_BKDR, reg); 640ef2ee5d0SMichal Meloun 641ef2ee5d0SMichal Meloun return (0); 642ef2ee5d0SMichal Meloun } 643ef2ee5d0SMichal Meloun 644ef2ee5d0SMichal Meloun static int 645ef2ee5d0SMichal Meloun tegra_ahci_probe(device_t dev) 646ef2ee5d0SMichal Meloun { 647ef2ee5d0SMichal Meloun 648ef2ee5d0SMichal Meloun if (!ofw_bus_status_okay(dev)) 649ef2ee5d0SMichal Meloun return (ENXIO); 650ef2ee5d0SMichal Meloun 651ef2ee5d0SMichal Meloun if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) 652ef2ee5d0SMichal Meloun return (ENXIO); 653ef2ee5d0SMichal Meloun 654*459dc61cSMark Johnston device_set_desc(dev, "AHCI SATA controller"); 655ef2ee5d0SMichal Meloun return (BUS_PROBE_DEFAULT); 656ef2ee5d0SMichal Meloun } 657ef2ee5d0SMichal Meloun 658ef2ee5d0SMichal Meloun static int 659ef2ee5d0SMichal Meloun tegra_ahci_attach(device_t dev) 660ef2ee5d0SMichal Meloun { 661ef2ee5d0SMichal Meloun struct tegra_ahci_sc *sc; 662ef2ee5d0SMichal Meloun struct ahci_controller *ctlr; 663ef2ee5d0SMichal Meloun phandle_t node; 664ef2ee5d0SMichal Meloun int rv, rid; 665ef2ee5d0SMichal Meloun 666ef2ee5d0SMichal Meloun sc = device_get_softc(dev); 667ef2ee5d0SMichal Meloun sc->dev = dev; 668ef2ee5d0SMichal Meloun ctlr = &sc->ctlr; 669ef2ee5d0SMichal Meloun node = ofw_bus_get_node(dev); 670b9cbd68dSMichal Meloun sc->soc = (struct ahci_soc *)ofw_bus_search_compatible(dev, 671b9cbd68dSMichal Meloun compat_data)->ocd_data; 672ef2ee5d0SMichal Meloun 673ef2ee5d0SMichal Meloun ctlr->r_rid = 0; 674ef2ee5d0SMichal Meloun ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 675ef2ee5d0SMichal Meloun &ctlr->r_rid, RF_ACTIVE); 676ef2ee5d0SMichal Meloun if (ctlr->r_mem == NULL) 677ef2ee5d0SMichal Meloun return (ENXIO); 678ef2ee5d0SMichal Meloun 679ef2ee5d0SMichal Meloun rid = 1; 680ef2ee5d0SMichal Meloun sc->sata_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 681ef2ee5d0SMichal Meloun &rid, RF_ACTIVE); 682ef2ee5d0SMichal Meloun if (sc->sata_mem == NULL) { 683ef2ee5d0SMichal Meloun rv = ENXIO; 684ef2ee5d0SMichal Meloun goto fail; 685ef2ee5d0SMichal Meloun } 686b9cbd68dSMichal Meloun 687b9cbd68dSMichal Meloun /* Aux is optionall */ 688b9cbd68dSMichal Meloun rid = 2; 689b9cbd68dSMichal Meloun sc->aux_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 690b9cbd68dSMichal Meloun &rid, RF_ACTIVE); 691b9cbd68dSMichal Meloun 692ef2ee5d0SMichal Meloun rv = get_fdt_resources(sc, node); 693ef2ee5d0SMichal Meloun if (rv != 0) { 694ef2ee5d0SMichal Meloun device_printf(sc->dev, "Failed to allocate FDT resource(s)\n"); 695ef2ee5d0SMichal Meloun goto fail; 696ef2ee5d0SMichal Meloun } 697ef2ee5d0SMichal Meloun 698ef2ee5d0SMichal Meloun rv = enable_fdt_resources(sc); 699ef2ee5d0SMichal Meloun if (rv != 0) { 700ef2ee5d0SMichal Meloun device_printf(sc->dev, "Failed to enable FDT resource(s)\n"); 701ef2ee5d0SMichal Meloun goto fail; 702ef2ee5d0SMichal Meloun } 703ef2ee5d0SMichal Meloun rv = tegra_ahci_ctrl_init(sc); 704ef2ee5d0SMichal Meloun if (rv != 0) { 705ef2ee5d0SMichal Meloun device_printf(sc->dev, "Failed to initialize controller)\n"); 706ef2ee5d0SMichal Meloun goto fail; 707ef2ee5d0SMichal Meloun } 708ef2ee5d0SMichal Meloun 709ef2ee5d0SMichal Meloun /* Setup controller defaults. */ 710ef2ee5d0SMichal Meloun ctlr->msi = 0; 711ef2ee5d0SMichal Meloun ctlr->numirqs = 1; 712ef2ee5d0SMichal Meloun ctlr->ccc = 0; 713ef2ee5d0SMichal Meloun 714ef2ee5d0SMichal Meloun /* Reset controller. */ 715ef2ee5d0SMichal Meloun rv = tegra_ahci_ctlr_reset(dev); 716ef2ee5d0SMichal Meloun if (rv != 0) 717ef2ee5d0SMichal Meloun goto fail; 718ef2ee5d0SMichal Meloun rv = ahci_attach(dev); 719ef2ee5d0SMichal Meloun return (rv); 720ef2ee5d0SMichal Meloun 721ef2ee5d0SMichal Meloun fail: 722ef2ee5d0SMichal Meloun /* XXX FDT stuff */ 723ef2ee5d0SMichal Meloun if (sc->sata_mem != NULL) 724ef2ee5d0SMichal Meloun bus_release_resource(dev, SYS_RES_MEMORY, 1, sc->sata_mem); 725ef2ee5d0SMichal Meloun if (ctlr->r_mem != NULL) 726ef2ee5d0SMichal Meloun bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, 727ef2ee5d0SMichal Meloun ctlr->r_mem); 728ef2ee5d0SMichal Meloun return (rv); 729ef2ee5d0SMichal Meloun } 730ef2ee5d0SMichal Meloun 731ef2ee5d0SMichal Meloun static int 732ef2ee5d0SMichal Meloun tegra_ahci_detach(device_t dev) 733ef2ee5d0SMichal Meloun { 734ef2ee5d0SMichal Meloun 735ef2ee5d0SMichal Meloun ahci_detach(dev); 736ef2ee5d0SMichal Meloun return (0); 737ef2ee5d0SMichal Meloun } 738ef2ee5d0SMichal Meloun 739ef2ee5d0SMichal Meloun static int 740ef2ee5d0SMichal Meloun tegra_ahci_suspend(device_t dev) 741ef2ee5d0SMichal Meloun { 742ef2ee5d0SMichal Meloun struct tegra_ahci_sc *sc = device_get_softc(dev); 743ef2ee5d0SMichal Meloun 744ef2ee5d0SMichal Meloun bus_generic_suspend(dev); 745ef2ee5d0SMichal Meloun /* Disable interupts, so the state change(s) doesn't trigger. */ 746ef2ee5d0SMichal Meloun ATA_OUTL(sc->ctlr.r_mem, AHCI_GHC, 747ef2ee5d0SMichal Meloun ATA_INL(sc->ctlr.r_mem, AHCI_GHC) & (~AHCI_GHC_IE)); 748ef2ee5d0SMichal Meloun return (0); 749ef2ee5d0SMichal Meloun } 750ef2ee5d0SMichal Meloun 751ef2ee5d0SMichal Meloun static int 752ef2ee5d0SMichal Meloun tegra_ahci_resume(device_t dev) 753ef2ee5d0SMichal Meloun { 754ef2ee5d0SMichal Meloun int res; 755ef2ee5d0SMichal Meloun 756ef2ee5d0SMichal Meloun if ((res = tegra_ahci_ctlr_reset(dev)) != 0) 757ef2ee5d0SMichal Meloun return (res); 758ef2ee5d0SMichal Meloun ahci_ctlr_setup(dev); 759ef2ee5d0SMichal Meloun return (bus_generic_resume(dev)); 760ef2ee5d0SMichal Meloun } 761ef2ee5d0SMichal Meloun 7621d59a5bbSMichal Meloun static device_method_t tegra_ahci_methods[] = { 763ef2ee5d0SMichal Meloun DEVMETHOD(device_probe, tegra_ahci_probe), 764ef2ee5d0SMichal Meloun DEVMETHOD(device_attach, tegra_ahci_attach), 765ef2ee5d0SMichal Meloun DEVMETHOD(device_detach, tegra_ahci_detach), 766ef2ee5d0SMichal Meloun DEVMETHOD(device_suspend, tegra_ahci_suspend), 767ef2ee5d0SMichal Meloun DEVMETHOD(device_resume, tegra_ahci_resume), 768ef2ee5d0SMichal Meloun DEVMETHOD(bus_print_child, ahci_print_child), 769ef2ee5d0SMichal Meloun DEVMETHOD(bus_alloc_resource, ahci_alloc_resource), 770ef2ee5d0SMichal Meloun DEVMETHOD(bus_release_resource, ahci_release_resource), 771ef2ee5d0SMichal Meloun DEVMETHOD(bus_setup_intr, ahci_setup_intr), 772ef2ee5d0SMichal Meloun DEVMETHOD(bus_teardown_intr, ahci_teardown_intr), 773ddfc9c4cSWarner Losh DEVMETHOD(bus_child_location, ahci_child_location), 774ef2ee5d0SMichal Meloun DEVMETHOD(bus_get_dma_tag, ahci_get_dma_tag), 775ef2ee5d0SMichal Meloun 776ef2ee5d0SMichal Meloun DEVMETHOD_END 777ef2ee5d0SMichal Meloun }; 7781d59a5bbSMichal Meloun 7794bda238aSMichal Meloun static DEFINE_CLASS_0(ahci, tegra_ahci_driver, tegra_ahci_methods, 7804bda238aSMichal Meloun sizeof(struct tegra_ahci_sc)); 78123802d41SJohn Baldwin DRIVER_MODULE(tegra_ahci, simplebus, tegra_ahci_driver, NULL, NULL); 782