ec/google/chromeec: Define ACPI_NOTIFY_CROS_EC_MKBP constant
[coreboot.git] / src / soc / intel / elkhartlake / tsn_gbe.c
blob6092824b84ab8673a71f8954485a4141581b4d98
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <console/console.h>
4 #include <delay.h>
5 #include <device/mdio.h>
6 #include <device/pci.h>
7 #include <device/pci_ids.h>
8 #include <device/pci_ops.h>
9 #include <intelblocks/lpss.h>
10 #include <soc/soc_chip.h>
11 #include <soc/tsn_gbe.h>
12 #include <timer.h>
14 static void program_mac_address(struct device *dev, void *base)
16 enum cb_err status;
17 uint8_t mac[MAC_ADDR_LEN];
19 /* Check first whether there is a valid MAC address available */
20 status = mainboard_get_mac_address(dev, mac);
21 if (status != CB_SUCCESS) {
22 printk(BIOS_INFO, "TSN GbE: No valid MAC address found\n");
23 return;
26 printk(BIOS_DEBUG, "TSN GbE: Programming MAC Address...\n");
28 /* Write the upper 16 bits of the first 6-byte MAC address */
29 clrsetbits32(base + TSN_MAC_ADD0_HIGH, 0xffff, ((mac[5] << 8) | mac[4]));
30 /* Write the lower 32 bits of the first 6-byte MAC address */
31 clrsetbits32(base + TSN_MAC_ADD0_LOW, 0xffffffff,
32 (mac[3] << 24) | (mac[2] << 16) | (mac[1] << 8) | mac[0]);
36 static void tsn_set_phy2mac_irq_polarity(struct device *dev, enum tsn_phy_irq_polarity pol)
38 uint16_t gcr_reg;
39 const struct mdio_bus_operations *mdio_ops;
41 mdio_ops = dev_get_mdio_ops(dev);
42 if (!mdio_ops)
43 return;
45 if (pol == RISING_EDGE) {
46 /* Read TSN adhoc PHY sublayer register - global configuration register */
47 gcr_reg = mdio_ops->read(dev, TSN_MAC_MDIO_ADHOC_ADR, TSN_MAC_MDIO_GCR);
48 gcr_reg |= TSN_MAC_PHY2MAC_INTR_POL;
49 mdio_ops->write(dev, TSN_MAC_MDIO_ADHOC_ADR, TSN_MAC_MDIO_GCR, gcr_reg);
53 static void gbe_tsn_enable(struct device *dev)
55 /* Ensure controller is in D0 state. */
56 lpss_set_power_state(PCI_DEV(0, PCI_SLOT(dev->path.pci.devfn),
57 PCI_FUNC(dev->path.pci.devfn)), STATE_D0);
60 static void gbe_tsn_init(struct device *dev)
62 /* Get the base address of the I/O registers in memory space */
63 struct resource *gbe_tsn_res = find_resource(dev, PCI_BASE_ADDRESS_0);
64 void *io_mem_base = (void *)(uintptr_t)gbe_tsn_res->base;
65 config_t *config = config_of(dev);
67 /* Program MAC address */
68 program_mac_address(dev, io_mem_base);
70 /* Set PHY-to-MAC IRQ polarity according to devicetree */
71 switch (dev->path.pci.devfn) {
72 case PCH_DEVFN_GBE:
73 tsn_set_phy2mac_irq_polarity(dev, config->pch_tsn_phy_irq_edge);
74 break;
75 case PCH_DEVFN_PSEGBE0:
76 tsn_set_phy2mac_irq_polarity(dev, config->pse_tsn_phy_irq_edge[0]);
77 break;
78 case PCH_DEVFN_PSEGBE1:
79 tsn_set_phy2mac_irq_polarity(dev, config->pse_tsn_phy_irq_edge[1]);
80 break;
84 static enum cb_err phy_gmii_ready(void *base)
86 struct stopwatch sw;
88 stopwatch_init_msecs_expire(&sw, GMII_TIMEOUT_MS);
89 do {
90 if (!(read32((base + MAC_MDIO_ADR)) & MAC_GMII_BUSY))
91 return CB_SUCCESS;
92 mdelay(1);
93 } while (!stopwatch_expired(&sw));
95 printk(BIOS_ERR, "%s Timeout after %lld msec\n", __func__,
96 stopwatch_duration_msecs(&sw));
97 return CB_ERR;
100 static uint16_t tsn_mdio_read(struct device *dev, uint8_t phy_adr, uint8_t reg_adr)
102 uint16_t data = 0;
103 struct resource *gbe_tsn_res = find_resource(dev, PCI_BASE_ADDRESS_0);
104 void *mmio_base = res2mmio(gbe_tsn_res, 0, 0);
106 if (!mmio_base)
107 return data;
109 clrsetbits32(mmio_base + MAC_MDIO_ADR, MAC_MDIO_ADR_MASK,
110 MAC_PHYAD(phy_adr) | MAC_REGAD(reg_adr)
111 | MAC_CLK_TRAIL_4 | MAC_CSR_CLK_DIV_102
112 | MAC_OP_CMD_READ | MAC_GMII_BUSY);
114 /* Wait for MDIO frame transfer to complete before reading MDIO DATA register. */
115 if (phy_gmii_ready(mmio_base) != CB_SUCCESS) {
116 printk(BIOS_ERR, "%s TSN GMII busy. PHY Adr: 0x%x, Reg 0x%x\n",
117 __func__, phy_adr, reg_adr);
118 } else {
119 data = read16(mmio_base + MAC_MDIO_DATA);
120 printk(BIOS_SPEW, "%s PHY Adr: 0x%x, Reg: 0x%x , Data: 0x%x\n",
121 __func__, phy_adr, reg_adr, data);
123 return data;
126 static void tsn_mdio_write(struct device *dev, uint8_t phy_adr, uint8_t reg_adr, uint16_t data)
128 struct resource *gbe_tsn_res = find_resource(dev, PCI_BASE_ADDRESS_0);
129 void *mmio_base = res2mmio(gbe_tsn_res, 0, 0);
131 if (!mmio_base)
132 return;
134 write16(mmio_base + MAC_MDIO_DATA, data);
135 clrsetbits32(mmio_base + MAC_MDIO_ADR, MAC_MDIO_ADR_MASK,
136 MAC_PHYAD(phy_adr) | MAC_REGAD(reg_adr)
137 | MAC_CLK_TRAIL_4 | MAC_CSR_CLK_DIV_102
138 | MAC_OP_CMD_WRITE | MAC_GMII_BUSY);
140 /* Wait for MDIO frame transfer to complete before exit. */
141 if (phy_gmii_ready(mmio_base) != CB_SUCCESS)
142 printk(BIOS_ERR, "%s TSN GMII busy. PHY Adr: 0x%x, Reg 0x%x\n",
143 __func__, phy_adr, reg_adr);
144 else
145 printk(BIOS_SPEW, "%s PHY Adr: 0x%x, Reg: 0x%x , Data: 0x%x\n",
146 __func__, phy_adr, reg_adr, data);
149 static struct mdio_bus_operations mdio_ops = {
150 .read = tsn_mdio_read,
151 .write = tsn_mdio_write,
154 static struct device_operations gbe_tsn_ops = {
155 .read_resources = pci_dev_read_resources,
156 .set_resources = pci_dev_set_resources,
157 .enable_resources = pci_dev_enable_resources,
158 .scan_bus = scan_generic_bus,
159 .enable = gbe_tsn_enable,
160 .init = gbe_tsn_init,
161 .ops_mdio = &mdio_ops,
164 static const unsigned short gbe_tsn_device_ids[] = {
165 PCI_DID_INTEL_EHL_GBE_HOST,
166 PCI_DID_INTEL_EHL_GBE_PSE_0,
167 PCI_DID_INTEL_EHL_GBE_PSE_1,
171 static const struct pci_driver gbe_tsn_driver __pci_driver = {
172 .ops = &gbe_tsn_ops,
173 .vendor = PCI_VID_INTEL,
174 .devices = gbe_tsn_device_ids,