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