1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2016 Google, Inc 4 * 5 * From coreboot src/soc/intel/broadwell/sata.c 6 */ 7 8#include <common.h> 9#include <dm.h> 10#include <log.h> 11#include <asm/global_data.h> 12#include <asm/gpio.h> 13#include <asm/io.h> 14#include <asm/intel_regs.h> 15#include <asm/lpc_common.h> 16#include <asm/pch_common.h> 17#include <asm/pch_common.h> 18#include <asm/arch/pch.h> 19#include <linux/delay.h> 20 21struct sata_plat { 22 int port_map; 23 uint port0_gen3_tx; 24 uint port1_gen3_tx; 25 uint port0_gen3_dtle; 26 uint port1_gen3_dtle; 27 28 /* 29 * SATA DEVSLP Mux 30 * 0 = port 0 DEVSLP on DEVSLP0/GPIO33 31 * 1 = port 3 DEVSLP on DEVSLP0/GPIO33 32 */ 33 int devslp_mux; 34 35 /* 36 * DEVSLP Disable 37 * 0: DEVSLP is enabled 38 * 1: DEVSLP is disabled 39 */ 40 int devslp_disable; 41}; 42 43static void broadwell_sata_init(struct udevice *dev) 44{ 45 struct sata_plat *plat = dev_get_plat(dev); 46 u32 reg32; 47 u8 *abar; 48 u16 reg16; 49 int port; 50 51 debug("SATA: Initializing controller in AHCI mode.\n"); 52 53 /* Set timings */ 54 dm_pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE); 55 dm_pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE); 56 57 /* for AHCI, Port Enable is managed in memory mapped space */ 58 dm_pci_read_config16(dev, 0x92, ®16); 59 reg16 &= ~0xf; 60 reg16 |= 0x8000 | plat->port_map; 61 dm_pci_write_config16(dev, 0x92, reg16); 62 udelay(2); 63 64 /* Setup register 98h */ 65 dm_pci_read_config32(dev, 0x98, ®32); 66 reg32 &= ~((1 << 31) | (1 << 30)); 67 reg32 |= 1 << 23; 68 reg32 |= 1 << 24; /* Enable MPHY Dynamic Power Gating */ 69 dm_pci_write_config32(dev, 0x98, reg32); 70 71 /* Setup register 9Ch */ 72 reg16 = 0; /* Disable alternate ID */ 73 reg16 = 1 << 5; /* BWG step 12 */ 74 dm_pci_write_config16(dev, 0x9c, reg16); 75 76 /* SATA Initialization register */ 77 reg32 = 0x183; 78 reg32 |= (plat->port_map ^ 0xf) << 24; 79 reg32 |= (plat->devslp_mux & 1) << 15; 80 dm_pci_write_config32(dev, 0x94, reg32); 81 82 /* Initialize AHCI memory-mapped space */ 83 dm_pci_read_config32(dev, PCI_BASE_ADDRESS_5, ®32); 84 abar = (u8 *)reg32; 85 debug("ABAR: %p\n", abar); 86 87 /* CAP (HBA Capabilities) : enable power management */ 88 clrsetbits_le32(abar + 0x00, 0x00020060 /* SXS+EMS+PMS */, 89 0x0c006000 /* PSC+SSC+SALP+SSS */ | 90 1 << 18); /* SAM: SATA AHCI MODE ONLY */ 91 92 /* PI (Ports implemented) */ 93 writel(plat->port_map, abar + 0x0c); 94 (void) readl(abar + 0x0c); /* Read back 1 */ 95 (void) readl(abar + 0x0c); /* Read back 2 */ 96 97 /* CAP2 (HBA Capabilities Extended)*/ 98 if (plat->devslp_disable) { 99 clrbits_le32(abar + 0x24, 1 << 3); 100 } else { 101 /* Enable DEVSLP */ 102 setbits_le32(abar + 0x24, 1 << 5 | 1 << 4 | 1 << 3 | 1 << 2); 103 104 for (port = 0; port < 4; port++) { 105 if (!(plat->port_map & (1 << port))) 106 continue; 107 /* DEVSLP DSP */ 108 setbits_le32(abar + 0x144 + (0x80 * port), 1 << 1); 109 } 110 } 111 112 /* Static Power Gating for unused ports */ 113 reg32 = readl(RCB_REG(0x3a84)); 114 /* Port 3 and 2 disabled */ 115 if ((plat->port_map & ((1 << 3)|(1 << 2))) == 0) 116 reg32 |= (1 << 24) | (1 << 26); 117 /* Port 1 and 0 disabled */ 118 if ((plat->port_map & ((1 << 1)|(1 << 0))) == 0) 119 reg32 |= (1 << 20) | (1 << 18); 120 writel(reg32, RCB_REG(0x3a84)); 121 122 /* Set Gen3 Transmitter settings if needed */ 123 if (plat->port0_gen3_tx) 124 pch_iobp_update(SATA_IOBP_SP0_SECRT88, 125 ~(SATA_SECRT88_VADJ_MASK << 126 SATA_SECRT88_VADJ_SHIFT), 127 (plat->port0_gen3_tx & 128 SATA_SECRT88_VADJ_MASK) 129 << SATA_SECRT88_VADJ_SHIFT); 130 131 if (plat->port1_gen3_tx) 132 pch_iobp_update(SATA_IOBP_SP1_SECRT88, 133 ~(SATA_SECRT88_VADJ_MASK << 134 SATA_SECRT88_VADJ_SHIFT), 135 (plat->port1_gen3_tx & 136 SATA_SECRT88_VADJ_MASK) 137 << SATA_SECRT88_VADJ_SHIFT); 138 139 /* Set Gen3 DTLE DATA / EDGE registers if needed */ 140 if (plat->port0_gen3_dtle) { 141 pch_iobp_update(SATA_IOBP_SP0DTLE_DATA, 142 ~(SATA_DTLE_MASK << SATA_DTLE_DATA_SHIFT), 143 (plat->port0_gen3_dtle & SATA_DTLE_MASK) 144 << SATA_DTLE_DATA_SHIFT); 145 146 pch_iobp_update(SATA_IOBP_SP0DTLE_EDGE, 147 ~(SATA_DTLE_MASK << SATA_DTLE_EDGE_SHIFT), 148 (plat->port0_gen3_dtle & SATA_DTLE_MASK) 149 << SATA_DTLE_EDGE_SHIFT); 150 } 151 152 if (plat->port1_gen3_dtle) { 153 pch_iobp_update(SATA_IOBP_SP1DTLE_DATA, 154 ~(SATA_DTLE_MASK << SATA_DTLE_DATA_SHIFT), 155 (plat->port1_gen3_dtle & SATA_DTLE_MASK) 156 << SATA_DTLE_DATA_SHIFT); 157 158 pch_iobp_update(SATA_IOBP_SP1DTLE_EDGE, 159 ~(SATA_DTLE_MASK << SATA_DTLE_EDGE_SHIFT), 160 (plat->port1_gen3_dtle & SATA_DTLE_MASK) 161 << SATA_DTLE_EDGE_SHIFT); 162 } 163 164 /* 165 * Additional Programming Requirements for Power Optimizer 166 */ 167 168 /* Step 1 */ 169 pch_common_sir_write(dev, 0x64, 0x883c9003); 170 171 /* Step 2: SIR 68h[15:0] = 880Ah */ 172 reg32 = pch_common_sir_read(dev, 0x68); 173 reg32 &= 0xffff0000; 174 reg32 |= 0x880a; 175 pch_common_sir_write(dev, 0x68, reg32); 176 177 /* Step 3: SIR 60h[3] = 1 */ 178 reg32 = pch_common_sir_read(dev, 0x60); 179 reg32 |= (1 << 3); 180 pch_common_sir_write(dev, 0x60, reg32); 181 182 /* Step 4: SIR 60h[0] = 1 */ 183 reg32 = pch_common_sir_read(dev, 0x60); 184 reg32 |= (1 << 0); 185 pch_common_sir_write(dev, 0x60, reg32); 186 187 /* Step 5: SIR 60h[1] = 1 */ 188 reg32 = pch_common_sir_read(dev, 0x60); 189 reg32 |= (1 << 1); 190 pch_common_sir_write(dev, 0x60, reg32); 191 192 /* Clock Gating */ 193 pch_common_sir_write(dev, 0x70, 0x3f00bf1f); 194 pch_common_sir_write(dev, 0x54, 0xcf000f0f); 195 pch_common_sir_write(dev, 0x58, 0x00190000); 196 clrsetbits_le32(RCB_REG(0x333c), 0x00300000, 0x00c00000); 197 198 dm_pci_read_config32(dev, 0x300, ®32); 199 reg32 |= 1 << 17 | 1 << 16 | 1 << 19; 200 reg32 |= 1 << 31 | 1 << 30 | 1 << 29; 201 dm_pci_write_config32(dev, 0x300, reg32); 202 203 dm_pci_read_config32(dev, 0x98, ®32); 204 reg32 |= 1 << 29; 205 dm_pci_write_config32(dev, 0x98, reg32); 206 207 /* Register Lock */ 208 dm_pci_read_config32(dev, 0x9c, ®32); 209 reg32 |= 1 << 31; 210 dm_pci_write_config32(dev, 0x9c, reg32); 211} 212 213static int broadwell_sata_enable(struct udevice *dev) 214{ 215 struct sata_plat *plat = dev_get_plat(dev); 216 struct gpio_desc desc; 217 u16 map; 218 int ret; 219 220 /* 221 * Set SATA controller mode early so the resource allocator can 222 * properly assign IO/Memory resources for the controller. 223 */ 224 map = 0x0060; 225 226 map |= (plat->port_map ^ 0x3f) << 8; 227 dm_pci_write_config16(dev, 0x90, map); 228 229 ret = gpio_request_by_name(dev, "reset-gpio", 0, &desc, GPIOD_IS_OUT); 230 if (ret) 231 return ret; 232 233 return 0; 234} 235 236static int broadwell_sata_of_to_plat(struct udevice *dev) 237{ 238 struct sata_plat *plat = dev_get_plat(dev); 239 const void *blob = gd->fdt_blob; 240 int node = dev_of_offset(dev); 241 242 plat->port_map = fdtdec_get_int(blob, node, "intel,sata-port-map", 0); 243 plat->port0_gen3_tx = fdtdec_get_int(blob, node, 244 "intel,sata-port0-gen3-tx", 0); 245 246 return 0; 247} 248 249static int broadwell_sata_probe(struct udevice *dev) 250{ 251 if (!(gd->flags & GD_FLG_RELOC)) 252 return broadwell_sata_enable(dev); 253 else 254 broadwell_sata_init(dev); 255 256 return 0; 257} 258 259static const struct udevice_id broadwell_ahci_ids[] = { 260 { .compatible = "intel,wildcatpoint-ahci" }, 261 { } 262}; 263 264U_BOOT_DRIVER(ahci_broadwell_drv) = { 265 .name = "ahci_broadwell", 266 .id = UCLASS_AHCI, 267 .of_match = broadwell_ahci_ids, 268 .of_to_plat = broadwell_sata_of_to_plat, 269 .probe = broadwell_sata_probe, 270 .plat_auto = sizeof(struct sata_plat), 271}; 272