1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <device/device.h>
4 #include <device/pci.h>
5 #include <device/pci_ids.h>
6 #include <device/pci_ops.h>
7
8 #include "hudson.h"
9
sata_init(struct device * dev)10 static void sata_init(struct device *dev)
11 {
12 #if CONFIG(SOUTHBRIDGE_AMD_PI_AVALON) || CONFIG(SOUTHBRIDGE_AMD_PI_KERN)
13 /**************************************
14 * Configure the SATA port multiplier *
15 **************************************/
16 #define BYTE_TO_DWORD_OFFSET(x) (x / 4)
17 #define AHCI_BASE_ADDRESS_REG 0x24
18 #define MISC_CONTROL_REG 0x40
19 #define UNLOCK_BIT (1 << 0)
20 #define SATA_CAPABILITIES_REG 0xFC
21 #define CFG_CAP_SPM (1 << 12)
22
23 volatile u32 *ahci_ptr =
24 (u32*)(pci_read_config32(dev, AHCI_BASE_ADDRESS_REG) & 0xFFFFFF00);
25 u32 temp;
26
27 /* unlock the write-protect */
28 temp = pci_read_config32(dev, MISC_CONTROL_REG);
29 temp |= UNLOCK_BIT;
30 pci_write_config32(dev, MISC_CONTROL_REG, temp);
31
32 /* set the SATA AHCI mode to allow port expanders */
33 *(ahci_ptr + BYTE_TO_DWORD_OFFSET(SATA_CAPABILITIES_REG)) |= CFG_CAP_SPM;
34
35 /* lock the write-protect */
36 temp = pci_read_config32(dev, MISC_CONTROL_REG);
37 temp &= ~UNLOCK_BIT;
38 pci_write_config32(dev, MISC_CONTROL_REG, temp);
39 #endif
40 };
41
42 static struct pci_operations lops_pci = {
43 /* .set_subsystem = pci_dev_set_subsystem, */
44 };
45
46 static struct device_operations sata_ops = {
47 .read_resources = pci_dev_read_resources,
48 .set_resources = pci_dev_set_resources,
49 .enable_resources = pci_dev_enable_resources,
50 .init = sata_init,
51 .ops_pci = &lops_pci,
52 };
53
54 static const unsigned short pci_device_ids[] = {
55 PCI_DID_AMD_SB900_SATA,
56 PCI_DID_AMD_SB900_SATA_AHCI,
57 PCI_DID_AMD_CZ_SATA,
58 PCI_DID_AMD_CZ_SATA_AHCI,
59 0
60 };
61
62 static const struct pci_driver sata0_driver __pci_driver = {
63 .ops = &sata_ops,
64 .vendor = PCI_VID_AMD,
65 .devices = pci_device_ids,
66 };
67