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