tegra_ahci.c revision 296936
1296936Smmel/*- 2296936Smmel * Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org> 3296936Smmel * All rights reserved. 4296936Smmel * 5296936Smmel * Redistribution and use in source and binary forms, with or without 6296936Smmel * modification, are permitted provided that the following conditions 7296936Smmel * are met: 8296936Smmel * 1. Redistributions of source code must retain the above copyright 9296936Smmel * notice, this list of conditions and the following disclaimer. 10296936Smmel * 2. Redistributions in binary form must reproduce the above copyright 11296936Smmel * notice, this list of conditions and the following disclaimer in the 12296936Smmel * documentation and/or other materials provided with the distribution. 13296936Smmel * 14296936Smmel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15296936Smmel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16296936Smmel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17296936Smmel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18296936Smmel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19296936Smmel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20296936Smmel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21296936Smmel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22296936Smmel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23296936Smmel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24296936Smmel * SUCH DAMAGE. 25296936Smmel */ 26296936Smmel 27296936Smmel#include <sys/cdefs.h> 28296936Smmel__FBSDID("$FreeBSD: head/sys/arm/nvidia/tegra_ahci.c 296936 2016-03-16 13:01:48Z mmel $"); 29296936Smmel 30296936Smmel/* 31296936Smmel * AHCI driver for Tegra SoCs. 32296936Smmel */ 33296936Smmel#include <sys/param.h> 34296936Smmel#include <sys/module.h> 35296936Smmel#include <sys/systm.h> 36296936Smmel#include <sys/bus.h> 37296936Smmel#include <sys/conf.h> 38296936Smmel#include <sys/endian.h> 39296936Smmel#include <sys/kernel.h> 40296936Smmel#include <sys/lock.h> 41296936Smmel#include <sys/malloc.h> 42296936Smmel#include <sys/mutex.h> 43296936Smmel#include <sys/rman.h> 44296936Smmel 45296936Smmel#include <machine/bus.h> 46296936Smmel#include <machine/resource.h> 47296936Smmel 48296936Smmel#include <dev/ahci/ahci.h> 49296936Smmel#include <dev/extres/clk/clk.h> 50296936Smmel#include <dev/extres/hwreset/hwreset.h> 51296936Smmel#include <dev/extres/phy/phy.h> 52296936Smmel#include <dev/extres/regulator/regulator.h> 53296936Smmel#include <dev/fdt/fdt_common.h> 54296936Smmel#include <dev/fdt/fdt_pinctrl.h> 55296936Smmel#include <dev/ofw/ofw_bus.h> 56296936Smmel#include <dev/ofw/ofw_bus_subr.h> 57296936Smmel 58296936Smmel#include <arm/nvidia/tegra_efuse.h> 59296936Smmel#include <arm/nvidia/tegra_pmc.h> 60296936Smmel 61296936Smmel#define AHCI_WR4(_sc, _r, _v) bus_write_4((_sc)->ctlr.r_mem, (_r), (_v)) 62296936Smmel#define AHCI_RD4(_sc, _r) bus_read_4((_sc)->ctlr.r_mem, (_r)) 63296936Smmel#define SATA_WR4(_sc, _r, _v) bus_write_4((_sc)->sata_mem, (_r), (_v)) 64296936Smmel#define SATA_RD4(_sc, _r) bus_read_4((_sc)->sata_mem, (_r)) 65296936Smmel 66296936Smmelstatic struct ofw_compat_data compat_data[] = { 67296936Smmel {"nvidia,tegra124-ahci", 1}, 68296936Smmel {NULL, 0} 69296936Smmel}; 70296936Smmel 71296936Smmelstruct tegra_ahci_sc { 72296936Smmel struct ahci_controller ctlr; /* Must be first */ 73296936Smmel device_t dev; 74296936Smmel struct resource *sata_mem; 75296936Smmel clk_t clk_sata; 76296936Smmel clk_t clk_sata_oob; 77296936Smmel clk_t clk_pll_e; 78296936Smmel clk_t clk_cml; 79296936Smmel hwreset_t hwreset_sata; 80296936Smmel hwreset_t hwreset_sata_oob; 81296936Smmel hwreset_t hwreset_sata_cold; 82296936Smmel regulator_t supply_hvdd; 83296936Smmel regulator_t supply_vddio; 84296936Smmel regulator_t supply_avdd; 85296936Smmel regulator_t supply_target_5v; 86296936Smmel regulator_t supply_target_12v; 87296936Smmel phy_t phy; 88296936Smmel}; 89296936Smmel 90296936Smmelstruct sata_pad_calibration { 91296936Smmel uint32_t gen1_tx_amp; 92296936Smmel uint32_t gen1_tx_peak; 93296936Smmel uint32_t gen2_tx_amp; 94296936Smmel uint32_t gen2_tx_peak; 95296936Smmel}; 96296936Smmel 97296936Smmelstatic const struct sata_pad_calibration tegra124_pad_calibration[] = { 98296936Smmel {0x18, 0x04, 0x18, 0x0a}, 99296936Smmel {0x0e, 0x04, 0x14, 0x0a}, 100296936Smmel {0x0e, 0x07, 0x1a, 0x0e}, 101296936Smmel {0x14, 0x0e, 0x1a, 0x0e}, 102296936Smmel}; 103296936Smmel 104296936Smmel#define SATA_CONFIGURATION 0x180 105296936Smmel#define SATA_CONFIGURATION_EN_FPCI (1 << 0) 106296936Smmel 107296936Smmel#define SATA_FPCI_BAR5 0x94 108296936Smmel#define SATA_FPCI_BAR5_START_SHIFT 4 109296936Smmel 110296936Smmel#define SATA_INTR_MASK 0x188 111296936Smmel#define SATA_INTR_MASK_IP_INT_MASK (1 << 16) 112296936Smmel 113296936Smmel#define SCFG_OFFSET 0x1000 114296936Smmel 115296936Smmel#define T_SATA0_CFG_1 0x04 116296936Smmel#define T_SATA0_CFG_1_IO_SPACE (1 << 0) 117296936Smmel#define T_SATA0_CFG_1_MEMORY_SPACE (1 << 1) 118296936Smmel#define T_SATA0_CFG_1_BUS_MASTER (1 << 2) 119296936Smmel#define T_SATA0_CFG_1_SERR (1 << 8) 120296936Smmel 121296936Smmel#define T_SATA0_CFG_9 0x24 122296936Smmel#define T_SATA0_CFG_9_BASE_ADDRESS_SHIFT 13 123296936Smmel 124296936Smmel#define T_SATA0_AHCI_HBA_CAP_BKDR 0x300 125296936Smmel#define T_SATA0_BKDOOR_CC 0x4a4 126296936Smmel#define T_SATA0_CFG_SATA 0x54c 127296936Smmel#define T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN (1 << 12) 128296936Smmel 129296936Smmel#define T_SATA0_CFG_MISC 0x550 130296936Smmel#define T_SATA0_INDEX 0x680 131296936Smmel 132296936Smmel#define T_SATA0_CHX_PHY_CTRL1_GEN1 0x690 133296936Smmel#define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_MASK 0xff 134296936Smmel#define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT 8 135296936Smmel#define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_MASK 0xff 136296936Smmel#define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT 0 137296936Smmel 138296936Smmel 139296936Smmel#define T_SATA0_CHX_PHY_CTRL1_GEN2 0x694 140296936Smmel#define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_MASK 0xff 141296936Smmel#define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_SHIFT 12 142296936Smmel#define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_MASK 0xff 143296936Smmel#define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_SHIFT 0 144296936Smmel 145296936Smmel#define T_SATA0_CHX_PHY_CTRL2 0x69c 146296936Smmel#define T_SATA0_CHX_PHY_CTRL2_CDR_CNTL_GEN1 0x23 147296936Smmel 148296936Smmel#define T_SATA0_CHX_PHY_CTRL11 0x6d0 149296936Smmel#define T_SATA0_CHX_PHY_CTRL11_GEN2_RX_EQ (0x2800 << 16) 150296936Smmel 151296936Smmel#define FUSE_SATA_CALIB 0x124 152296936Smmel#define FUSE_SATA_CALIB_MASK 0x3 153296936Smmel 154296936Smmel 155296936Smmel#define SATA_AUX_MISC_CNTL 0x1108 156296936Smmel#define SATA_AUX_PAD_PLL_CTRL_0 0x1120 157296936Smmel#define SATA_AUX_PAD_PLL_CTRL_1 0x1124 158296936Smmel#define SATA_AUX_PAD_PLL_CTRL_2 0x1128 159296936Smmel#define SATA_AUX_PAD_PLL_CTRL_3 0x112c 160296936Smmel 161296936Smmel#define T_AHCI_HBA_CCC_PORTS 0x0018 162296936Smmel#define T_AHCI_HBA_CAP_BKDR 0x00A0 163296936Smmel#define T_AHCI_HBA_CAP_BKDR_S64A (1 << 31) 164296936Smmel#define T_AHCI_HBA_CAP_BKDR_SNCQ (1 << 30) 165296936Smmel#define T_AHCI_HBA_CAP_BKDR_SSNTF (1 << 29) 166296936Smmel#define T_AHCI_HBA_CAP_BKDR_SMPS (1 << 28) 167296936Smmel#define T_AHCI_HBA_CAP_BKDR_SUPP_STG_SPUP (1 << 27) 168296936Smmel#define T_AHCI_HBA_CAP_BKDR_SALP (1 << 26) 169296936Smmel#define T_AHCI_HBA_CAP_BKDR_SAL (1 << 25) 170296936Smmel#define T_AHCI_HBA_CAP_BKDR_SUPP_CLO (1 << 24) 171296936Smmel#define T_AHCI_HBA_CAP_BKDR_INTF_SPD_SUPP(x) (((x) & 0xF) << 20) 172296936Smmel#define T_AHCI_HBA_CAP_BKDR_SUPP_NONZERO_OFFSET (1 << 19) 173296936Smmel#define T_AHCI_HBA_CAP_BKDR_SUPP_AHCI_ONLY (1 << 18) 174296936Smmel#define T_AHCI_HBA_CAP_BKDR_SUPP_PM (1 << 17) 175296936Smmel#define T_AHCI_HBA_CAP_BKDR_FIS_SWITCHING (1 << 16) 176296936Smmel#define T_AHCI_HBA_CAP_BKDR_PIO_MULT_DRQ_BLK (1 << 15) 177296936Smmel#define T_AHCI_HBA_CAP_BKDR_SLUMBER_ST_CAP (1 << 14) 178296936Smmel#define T_AHCI_HBA_CAP_BKDR_PARTIAL_ST_CAP (1 << 13) 179296936Smmel#define T_AHCI_HBA_CAP_BKDR_NUM_CMD_SLOTS(x) (((x) & 0x1F) << 8) 180296936Smmel#define T_AHCI_HBA_CAP_BKDR_CMD_CMPL_COALESING (1 << 7) 181296936Smmel#define T_AHCI_HBA_CAP_BKDR_ENCL_MGMT_SUPP (1 << 6) 182296936Smmel#define T_AHCI_HBA_CAP_BKDR_EXT_SATA (1 << 5) 183296936Smmel#define T_AHCI_HBA_CAP_BKDR_NUM_PORTS(x) (((x) & 0xF) << 0) 184296936Smmel 185296936Smmel#define T_AHCI_PORT_BKDR 0x0170 186296936Smmel 187296936Smmel#define T_AHCI_PORT_BKDR_PXDEVSLP_DETO_OVERRIDE_VAL(x) (((x) & 0xFF) << 24) 188296936Smmel#define T_AHCI_PORT_BKDR_PXDEVSLP_MDAT_OVERRIDE_VAL(x) (((x) & 0x1F) << 16) 189296936Smmel#define T_AHCI_PORT_BKDR_PXDEVSLP_DETO_OVERRIDE (1 << 15) 190296936Smmel#define T_AHCI_PORT_BKDR_PXDEVSLP_MDAT_OVERRIDE (1 << 14) 191296936Smmel#define T_AHCI_PORT_BKDR_PXDEVSLP_DM(x) (((x) & 0xF) << 10) 192296936Smmel#define T_AHCI_PORT_BKDR_PORT_UNCONNECTED (1 << 9) 193296936Smmel#define T_AHCI_PORT_BKDR_CLK_CLAMP_CTRL_CLAMP_THIS_CH (1 << 8) 194296936Smmel#define T_AHCI_PORT_BKDR_CLK_CLAMP_CTRL_TXRXCLK_UNCLAMP (1 << 7) 195296936Smmel#define T_AHCI_PORT_BKDR_CLK_CLAMP_CTRL_TXRXCLK_CLAMP (1 << 6) 196296936Smmel#define T_AHCI_PORT_BKDR_CLK_CLAMP_CTRL_DEVCLK_UNCLAMP (1 << 5) 197296936Smmel#define T_AHCI_PORT_BKDR_CLK_CLAMP_CTRL_DEVCLK_CLAMP (1 << 4) 198296936Smmel#define T_AHCI_PORT_BKDR_HOTPLUG_CAP (1 << 3) 199296936Smmel#define T_AHCI_PORT_BKDR_MECH_SWITCH (1 << 2) 200296936Smmel#define T_AHCI_PORT_BKDR_COLD_PRSN_DET (1 << 1) 201296936Smmel#define T_AHCI_PORT_BKDR_EXT_SATA_SUPP (1 << 0) 202296936Smmel 203296936Smmelstatic int 204296936Smmelget_fdt_resources(struct tegra_ahci_sc *sc, phandle_t node) 205296936Smmel{ 206296936Smmel int rv; 207296936Smmel 208296936Smmel 209296936Smmel rv = regulator_get_by_ofw_property(sc->dev, "hvdd-supply", 210296936Smmel &sc->supply_hvdd ); 211296936Smmel if (rv != 0) { 212296936Smmel device_printf(sc->dev, "Cannot get 'hvdd' regulator\n"); 213296936Smmel return (ENXIO); 214296936Smmel } 215296936Smmel rv = regulator_get_by_ofw_property(sc->dev, "vddio-supply", 216296936Smmel &sc->supply_vddio); 217296936Smmel if (rv != 0) { 218296936Smmel device_printf(sc->dev, "Cannot get 'vddio' regulator\n"); 219296936Smmel return (ENXIO); 220296936Smmel } 221296936Smmel rv = regulator_get_by_ofw_property(sc->dev, "avdd-supply", 222296936Smmel &sc->supply_avdd); 223296936Smmel if (rv != 0) { 224296936Smmel device_printf(sc->dev, "Cannot get 'avdd' regulator\n"); 225296936Smmel return (ENXIO); 226296936Smmel } 227296936Smmel rv = regulator_get_by_ofw_property(sc->dev, "target-5v-supply", 228296936Smmel &sc->supply_target_5v); 229296936Smmel if (rv != 0) { 230296936Smmel device_printf(sc->dev, "Cannot get 'target-5v' regulator\n"); 231296936Smmel return (ENXIO); 232296936Smmel } 233296936Smmel rv = regulator_get_by_ofw_property(sc->dev, "target-12v-supply", 234296936Smmel &sc->supply_target_12v); 235296936Smmel if (rv != 0) { 236296936Smmel device_printf(sc->dev, "Cannot get 'target-12v' regulator\n"); 237296936Smmel return (ENXIO); 238296936Smmel } 239296936Smmel 240296936Smmel rv = hwreset_get_by_ofw_name(sc->dev, "sata", &sc->hwreset_sata ); 241296936Smmel if (rv != 0) { 242296936Smmel device_printf(sc->dev, "Cannot get 'sata' reset\n"); 243296936Smmel return (ENXIO); 244296936Smmel } 245296936Smmel rv = hwreset_get_by_ofw_name(sc->dev, "sata-oob", 246296936Smmel &sc->hwreset_sata_oob); 247296936Smmel if (rv != 0) { 248296936Smmel device_printf(sc->dev, "Cannot get 'sata oob' reset\n"); 249296936Smmel return (ENXIO); 250296936Smmel } 251296936Smmel rv = hwreset_get_by_ofw_name(sc->dev, "sata-cold", 252296936Smmel &sc->hwreset_sata_cold); 253296936Smmel if (rv != 0) { 254296936Smmel device_printf(sc->dev, "Cannot get 'sata cold' reset\n"); 255296936Smmel return (ENXIO); 256296936Smmel } 257296936Smmel 258296936Smmel rv = phy_get_by_ofw_name(sc->dev, "sata-phy", &sc->phy); 259296936Smmel if (rv != 0) { 260296936Smmel device_printf(sc->dev, "Cannot get 'sata' phy\n"); 261296936Smmel return (ENXIO); 262296936Smmel } 263296936Smmel 264296936Smmel rv = clk_get_by_ofw_name(sc->dev, "sata", &sc->clk_sata); 265296936Smmel if (rv != 0) { 266296936Smmel device_printf(sc->dev, "Cannot get 'sata' clock\n"); 267296936Smmel return (ENXIO); 268296936Smmel } 269296936Smmel rv = clk_get_by_ofw_name(sc->dev, "sata-oob", &sc->clk_sata_oob); 270296936Smmel if (rv != 0) { 271296936Smmel device_printf(sc->dev, "Cannot get 'sata oob' clock\n"); 272296936Smmel return (ENXIO); 273296936Smmel } 274296936Smmel rv = clk_get_by_ofw_name(sc->dev, "cml1", &sc->clk_cml); 275296936Smmel if (rv != 0) { 276296936Smmel device_printf(sc->dev, "Cannot get 'cml1' clock\n"); 277296936Smmel return (ENXIO); 278296936Smmel } 279296936Smmel rv = clk_get_by_ofw_name(sc->dev, "pll_e", &sc->clk_pll_e); 280296936Smmel if (rv != 0) { 281296936Smmel device_printf(sc->dev, "Cannot get 'pll_e' clock\n"); 282296936Smmel return (ENXIO); 283296936Smmel } 284296936Smmel return (0); 285296936Smmel} 286296936Smmel 287296936Smmelstatic int 288296936Smmelenable_fdt_resources(struct tegra_ahci_sc *sc) 289296936Smmel{ 290296936Smmel int rv; 291296936Smmel 292296936Smmel rv = regulator_enable(sc->supply_hvdd); 293296936Smmel if (rv != 0) { 294296936Smmel device_printf(sc->dev, "Cannot enable 'hvdd' regulator\n"); 295296936Smmel return (rv); 296296936Smmel } 297296936Smmel rv = regulator_enable(sc->supply_vddio); 298296936Smmel if (rv != 0) { 299296936Smmel device_printf(sc->dev, "Cannot enable 'vddio' regulator\n"); 300296936Smmel return (rv); 301296936Smmel } 302296936Smmel rv = regulator_enable(sc->supply_avdd); 303296936Smmel if (rv != 0) { 304296936Smmel device_printf(sc->dev, "Cannot enable 'avdd' regulator\n"); 305296936Smmel return (rv); 306296936Smmel } 307296936Smmel rv = regulator_enable(sc->supply_target_5v); 308296936Smmel if (rv != 0) { 309296936Smmel device_printf(sc->dev, 310296936Smmel "Cannot enable 'target-5v' regulator\n"); 311296936Smmel return (rv); 312296936Smmel } 313296936Smmel rv = regulator_enable(sc->supply_target_12v); 314296936Smmel if (rv != 0) { 315296936Smmel device_printf(sc->dev, 316296936Smmel "Cannot enable 'sc->target-12v' regulator\n"); 317296936Smmel return (rv); 318296936Smmel } 319296936Smmel 320296936Smmel /* Stop clocks */ 321296936Smmel clk_stop(sc->clk_sata); 322296936Smmel clk_stop(sc->clk_sata_oob); 323296936Smmel tegra_powergate_power_off(TEGRA_POWERGATE_SAX); 324296936Smmel 325296936Smmel rv = hwreset_assert(sc->hwreset_sata); 326296936Smmel if (rv != 0) { 327296936Smmel device_printf(sc->dev, "Cannot assert 'sata' reset\n"); 328296936Smmel return (rv); 329296936Smmel } 330296936Smmel rv = hwreset_assert(sc->hwreset_sata_oob); 331296936Smmel if (rv != 0) { 332296936Smmel device_printf(sc->dev, "Cannot assert 'sata oob' reset\n"); 333296936Smmel return (rv); 334296936Smmel } 335296936Smmel 336296936Smmel rv = hwreset_assert(sc->hwreset_sata_cold); 337296936Smmel if (rv != 0) { 338296936Smmel device_printf(sc->dev, "Cannot assert 'sata cold' reset\n"); 339296936Smmel return (rv); 340296936Smmel } 341296936Smmel rv = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_SAX, 342296936Smmel sc->clk_sata, sc->hwreset_sata); 343296936Smmel if (rv != 0) { 344296936Smmel device_printf(sc->dev, "Cannot enable 'SAX' powergate\n"); 345296936Smmel return (rv); 346296936Smmel } 347296936Smmel 348296936Smmel rv = clk_enable(sc->clk_sata_oob); 349296936Smmel if (rv != 0) { 350296936Smmel device_printf(sc->dev, "Cannot enable 'sata oob' clock\n"); 351296936Smmel return (rv); 352296936Smmel } 353296936Smmel rv = clk_enable(sc->clk_cml); 354296936Smmel if (rv != 0) { 355296936Smmel device_printf(sc->dev, "Cannot enable 'cml' clock\n"); 356296936Smmel return (rv); 357296936Smmel } 358296936Smmel rv = clk_enable(sc->clk_pll_e); 359296936Smmel if (rv != 0) { 360296936Smmel device_printf(sc->dev, "Cannot enable 'pll e' clock\n"); 361296936Smmel return (rv); 362296936Smmel } 363296936Smmel 364296936Smmel rv = hwreset_deassert(sc->hwreset_sata_cold); 365296936Smmel if (rv != 0) { 366296936Smmel device_printf(sc->dev, "Cannot unreset 'sata cold' reset\n"); 367296936Smmel return (rv); 368296936Smmel } 369296936Smmel rv = hwreset_deassert(sc->hwreset_sata_oob); 370296936Smmel if (rv != 0) { 371296936Smmel device_printf(sc->dev, "Cannot unreset 'sata oob' reset\n"); 372296936Smmel return (rv); 373296936Smmel } 374296936Smmel 375296936Smmel rv = phy_enable(sc->dev, sc->phy); 376296936Smmel if (rv != 0) { 377296936Smmel device_printf(sc->dev, "Cannot enable SATA phy\n"); 378296936Smmel return (rv); 379296936Smmel } 380296936Smmel 381296936Smmel return (0); 382296936Smmel} 383296936Smmel 384296936Smmelstatic int 385296936Smmeltegra_ahci_ctrl_init(struct tegra_ahci_sc *sc) 386296936Smmel{ 387296936Smmel uint32_t val; 388296936Smmel const struct sata_pad_calibration *calib; 389296936Smmel 390296936Smmel val = SATA_RD4(sc, SATA_CONFIGURATION); 391296936Smmel val |= SATA_CONFIGURATION_EN_FPCI; 392296936Smmel SATA_WR4(sc, SATA_CONFIGURATION, val); 393296936Smmel 394296936Smmel 395296936Smmel /* Pad calibration. */ 396296936Smmel val = tegra_fuse_read_4(FUSE_SATA_CALIB); 397296936Smmel calib = tegra124_pad_calibration + (val & FUSE_SATA_CALIB_MASK); 398296936Smmel SATA_WR4(sc, SCFG_OFFSET + T_SATA0_INDEX, 1); 399296936Smmel 400296936Smmel val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN1); 401296936Smmel val &= ~(T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_MASK << 402296936Smmel T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT); 403296936Smmel val &= ~(T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_MASK << 404296936Smmel T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT); 405296936Smmel val |= calib->gen1_tx_amp << T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT; 406296936Smmel val |= calib->gen1_tx_peak << T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT; 407296936Smmel SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN1, val); 408296936Smmel 409296936Smmel val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN2); 410296936Smmel val &= ~(T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_MASK << 411296936Smmel T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_SHIFT); 412296936Smmel val &= ~(T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_MASK << 413296936Smmel T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_SHIFT); 414296936Smmel val |= calib->gen2_tx_amp << T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_SHIFT; 415296936Smmel val |= calib->gen2_tx_peak << T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_SHIFT; 416296936Smmel SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN2, val); 417296936Smmel 418296936Smmel SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL11, 419296936Smmel T_SATA0_CHX_PHY_CTRL11_GEN2_RX_EQ); 420296936Smmel 421296936Smmel SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL2, 422296936Smmel T_SATA0_CHX_PHY_CTRL2_CDR_CNTL_GEN1); 423296936Smmel 424296936Smmel SATA_WR4(sc, SCFG_OFFSET + T_SATA0_INDEX, 0); 425296936Smmel 426296936Smmel /* Set device ID. */ 427296936Smmel val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_SATA); 428296936Smmel val |= T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN; 429296936Smmel SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_SATA, val); 430296936Smmel 431296936Smmel SATA_WR4(sc, SCFG_OFFSET + T_SATA0_BKDOOR_CC, 0x01060100); 432296936Smmel 433296936Smmel val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_SATA); 434296936Smmel val &= ~T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN; 435296936Smmel SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_SATA, val); 436296936Smmel 437296936Smmel /* Enable IO & memory access, bus master mode */ 438296936Smmel val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_1); 439296936Smmel val |= T_SATA0_CFG_1_IO_SPACE; 440296936Smmel val |= T_SATA0_CFG_1_MEMORY_SPACE; 441296936Smmel val |= T_SATA0_CFG_1_BUS_MASTER; 442296936Smmel val |= T_SATA0_CFG_1_SERR; 443296936Smmel SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_1, val); 444296936Smmel 445296936Smmel /* SATA MMIO. */ 446296936Smmel SATA_WR4(sc, SATA_FPCI_BAR5, 0x10000 << SATA_FPCI_BAR5_START_SHIFT); 447296936Smmel /* AHCI bar */ 448296936Smmel SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_9, 449296936Smmel 0x08000 << T_SATA0_CFG_9_BASE_ADDRESS_SHIFT); 450296936Smmel 451296936Smmel /* Unmask interrupts. */ 452296936Smmel val = SATA_RD4(sc, SATA_INTR_MASK); 453296936Smmel val |= SATA_INTR_MASK_IP_INT_MASK; 454296936Smmel SATA_WR4(sc, SATA_INTR_MASK, val); 455296936Smmel 456296936Smmel return (0); 457296936Smmel} 458296936Smmel 459296936Smmelstatic int 460296936Smmeltegra_ahci_ctlr_reset(device_t dev) 461296936Smmel{ 462296936Smmel struct tegra_ahci_sc *sc; 463296936Smmel int rv; 464296936Smmel uint32_t reg; 465296936Smmel 466296936Smmel sc = device_get_softc(dev); 467296936Smmel rv = ahci_ctlr_reset(dev); 468296936Smmel if (rv != 0) 469296936Smmel return (0); 470296936Smmel AHCI_WR4(sc, T_AHCI_HBA_CCC_PORTS, 1); 471296936Smmel 472296936Smmel /* Overwrite AHCI capabilites. */ 473296936Smmel reg = AHCI_RD4(sc, T_AHCI_HBA_CAP_BKDR); 474296936Smmel reg &= ~T_AHCI_HBA_CAP_BKDR_NUM_PORTS(~0); 475296936Smmel reg |= T_AHCI_HBA_CAP_BKDR_NUM_PORTS(0); 476296936Smmel reg |= T_AHCI_HBA_CAP_BKDR_EXT_SATA; 477296936Smmel reg |= T_AHCI_HBA_CAP_BKDR_ENCL_MGMT_SUPP; 478296936Smmel reg |= T_AHCI_HBA_CAP_BKDR_CMD_CMPL_COALESING; 479296936Smmel reg |= T_AHCI_HBA_CAP_BKDR_FIS_SWITCHING; 480296936Smmel reg |= T_AHCI_HBA_CAP_BKDR_SUPP_PM; 481296936Smmel reg |= T_AHCI_HBA_CAP_BKDR_SUPP_CLO; 482296936Smmel reg |= T_AHCI_HBA_CAP_BKDR_SUPP_STG_SPUP; 483296936Smmel AHCI_WR4(sc, T_AHCI_HBA_CAP_BKDR, reg); 484296936Smmel 485296936Smmel /* Overwrite AHCI portcapabilites. */ 486296936Smmel reg = AHCI_RD4(sc, T_AHCI_PORT_BKDR); 487296936Smmel reg |= T_AHCI_PORT_BKDR_COLD_PRSN_DET; 488296936Smmel reg |= T_AHCI_PORT_BKDR_HOTPLUG_CAP; 489296936Smmel reg |= T_AHCI_PORT_BKDR_EXT_SATA_SUPP; 490296936Smmel AHCI_WR4(sc, T_AHCI_PORT_BKDR, reg); 491296936Smmel 492296936Smmel return (0); 493296936Smmel} 494296936Smmel 495296936Smmelstatic int 496296936Smmeltegra_ahci_probe(device_t dev) 497296936Smmel{ 498296936Smmel 499296936Smmel if (!ofw_bus_status_okay(dev)) 500296936Smmel return (ENXIO); 501296936Smmel 502296936Smmel if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) 503296936Smmel return (ENXIO); 504296936Smmel 505296936Smmel device_set_desc_copy(dev, "AHCI SATA controller"); 506296936Smmel return (BUS_PROBE_DEFAULT); 507296936Smmel} 508296936Smmel 509296936Smmelstatic int 510296936Smmeltegra_ahci_attach(device_t dev) 511296936Smmel{ 512296936Smmel struct tegra_ahci_sc *sc; 513296936Smmel struct ahci_controller *ctlr; 514296936Smmel phandle_t node; 515296936Smmel int rv, rid; 516296936Smmel 517296936Smmel sc = device_get_softc(dev); 518296936Smmel sc->dev = dev; 519296936Smmel ctlr = &sc->ctlr; 520296936Smmel node = ofw_bus_get_node(dev); 521296936Smmel 522296936Smmel ctlr->r_rid = 0; 523296936Smmel ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 524296936Smmel &ctlr->r_rid, RF_ACTIVE); 525296936Smmel if (ctlr->r_mem == NULL) 526296936Smmel return (ENXIO); 527296936Smmel 528296936Smmel rid = 1; 529296936Smmel sc->sata_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 530296936Smmel &rid, RF_ACTIVE); 531296936Smmel if (sc->sata_mem == NULL) { 532296936Smmel rv = ENXIO; 533296936Smmel goto fail; 534296936Smmel } 535296936Smmel rv = get_fdt_resources(sc, node); 536296936Smmel if (rv != 0) { 537296936Smmel device_printf(sc->dev, "Failed to allocate FDT resource(s)\n"); 538296936Smmel goto fail; 539296936Smmel } 540296936Smmel 541296936Smmel rv = enable_fdt_resources(sc); 542296936Smmel if (rv != 0) { 543296936Smmel device_printf(sc->dev, "Failed to enable FDT resource(s)\n"); 544296936Smmel goto fail; 545296936Smmel } 546296936Smmel rv = tegra_ahci_ctrl_init(sc); 547296936Smmel if (rv != 0) { 548296936Smmel device_printf(sc->dev, "Failed to initialize controller)\n"); 549296936Smmel goto fail; 550296936Smmel } 551296936Smmel 552296936Smmel /* Setup controller defaults. */ 553296936Smmel ctlr->msi = 0; 554296936Smmel ctlr->numirqs = 1; 555296936Smmel ctlr->ccc = 0; 556296936Smmel 557296936Smmel /* Reset controller. */ 558296936Smmel rv = tegra_ahci_ctlr_reset(dev); 559296936Smmel if (rv != 0) 560296936Smmel goto fail; 561296936Smmel rv = ahci_attach(dev); 562296936Smmel return (rv); 563296936Smmel 564296936Smmelfail: 565296936Smmel /* XXX FDT stuff */ 566296936Smmel if (sc->sata_mem != NULL) 567296936Smmel bus_release_resource(dev, SYS_RES_MEMORY, 1, sc->sata_mem); 568296936Smmel if (ctlr->r_mem != NULL) 569296936Smmel bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, 570296936Smmel ctlr->r_mem); 571296936Smmel return (rv); 572296936Smmel} 573296936Smmel 574296936Smmelstatic int 575296936Smmeltegra_ahci_detach(device_t dev) 576296936Smmel{ 577296936Smmel 578296936Smmel ahci_detach(dev); 579296936Smmel return (0); 580296936Smmel} 581296936Smmel 582296936Smmelstatic int 583296936Smmeltegra_ahci_suspend(device_t dev) 584296936Smmel{ 585296936Smmel struct tegra_ahci_sc *sc = device_get_softc(dev); 586296936Smmel 587296936Smmel bus_generic_suspend(dev); 588296936Smmel /* Disable interupts, so the state change(s) doesn't trigger. */ 589296936Smmel ATA_OUTL(sc->ctlr.r_mem, AHCI_GHC, 590296936Smmel ATA_INL(sc->ctlr.r_mem, AHCI_GHC) & (~AHCI_GHC_IE)); 591296936Smmel return (0); 592296936Smmel} 593296936Smmel 594296936Smmelstatic int 595296936Smmeltegra_ahci_resume(device_t dev) 596296936Smmel{ 597296936Smmel int res; 598296936Smmel 599296936Smmel if ((res = tegra_ahci_ctlr_reset(dev)) != 0) 600296936Smmel return (res); 601296936Smmel ahci_ctlr_setup(dev); 602296936Smmel return (bus_generic_resume(dev)); 603296936Smmel} 604296936Smmel 605296936Smmeldevclass_t genahci_devclass; 606296936Smmelstatic device_method_t genahci_methods[] = { 607296936Smmel DEVMETHOD(device_probe, tegra_ahci_probe), 608296936Smmel DEVMETHOD(device_attach, tegra_ahci_attach), 609296936Smmel DEVMETHOD(device_detach, tegra_ahci_detach), 610296936Smmel DEVMETHOD(device_suspend, tegra_ahci_suspend), 611296936Smmel DEVMETHOD(device_resume, tegra_ahci_resume), 612296936Smmel DEVMETHOD(bus_print_child, ahci_print_child), 613296936Smmel DEVMETHOD(bus_alloc_resource, ahci_alloc_resource), 614296936Smmel DEVMETHOD(bus_release_resource, ahci_release_resource), 615296936Smmel DEVMETHOD(bus_setup_intr, ahci_setup_intr), 616296936Smmel DEVMETHOD(bus_teardown_intr, ahci_teardown_intr), 617296936Smmel DEVMETHOD(bus_child_location_str, ahci_child_location_str), 618296936Smmel DEVMETHOD(bus_get_dma_tag, ahci_get_dma_tag), 619296936Smmel 620296936Smmel DEVMETHOD_END 621296936Smmel}; 622296936Smmelstatic driver_t genahci_driver = { 623296936Smmel "ahci", 624296936Smmel genahci_methods, 625296936Smmel sizeof(struct tegra_ahci_sc) 626296936Smmel}; 627296936SmmelDRIVER_MODULE(genahci, simplebus, genahci_driver, genahci_devclass, NULL, NULL); 628