1 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <device/device.h>
5 #include <console/console.h>
6 #include <device/pci.h>
7 #include <device/pci_ids.h>
8 #include <device/pci_ops.h>
13 /* This is a private function to wait for a bit mask in a given register */
14 /* To avoid endless loops, a time-out is implemented here. */
15 static int wait_done(uint32_t *reg
, uint32_t mask
)
17 uint32_t timeout
= I210_POLL_TIMEOUT_US
;
19 while (!(*reg
& mask
)) {
22 return I210_NOT_READY
;
27 /** \brief This function can read the configuration space of the MACPHY
28 * For this purpose, the EEPROM interface is used. No direct access
29 * to the flash memory will be done.
30 * @param *dev Pointer to the PCI device of this MACPHY
31 * @param address Address inside the flash where reading will start
32 * @param count Number of words (16 bit values) to read
33 * @param *buffer Pointer to the buffer where to store read data
34 * @return void I210_NO_ERROR or an error code
36 static uint32_t read_flash(struct device
*dev
, uint32_t address
,
37 uint32_t count
, uint16_t *buffer
)
43 /* Get the BAR to memory mapped space*/
44 bar
= pci_read_config32(dev
, PCI_BASE_ADDRESS_0
);
45 if ((!bar
) || ((address
+ count
) > 0x40))
46 return I210_INVALID_PARAM
;
47 eeprd
= (uint32_t *)(bar
+ I210_REG_EEREAD
);
48 /* Prior to start ensure flash interface is ready by checking DONE-bit */
49 if (wait_done(eeprd
, I210_DONE
))
50 return I210_NOT_READY
;
52 /*OK, interface is ready, we can use it now */
53 for (i
= 0; i
< count
; i
++) {
54 /* To start a read cycle write desired address in bits 12..2 */
55 *eeprd
= ((address
+ i
) << 2) & 0x1FFC;
56 /* Wait until read is done */
57 if (wait_done(eeprd
, I210_DONE
))
58 return I210_READ_ERROR
;
59 /* Here, we can read back desired word in bits 31..16 */
60 buffer
[i
] = (*eeprd
& 0xffff0000) >> 16;
65 /** \brief This function computes the checksum for the configuration space.
66 * The address range for the checksum is 0x00..0x3e.
67 * @param *dev Pointer to the PCI device of this MACPHY
68 * @param *checksum Pointer to the buffer where to store the checksum
69 * @return void I210_NO_ERROR or an error code
71 static uint32_t compute_checksum(struct device
*dev
, uint16_t *checksum
)
73 uint16_t eep_data
[0x40];
76 /* First read back data to compute the checksum for */
77 if (read_flash(dev
, 0, 0x3f, eep_data
))
78 return I210_READ_ERROR
;
79 /* The checksum is computed in that way that after summarize all the */
80 /* data from word address 0 to 0x3f the result is 0xBABA. */
82 for (i
= 0; i
< 0x3f; i
++)
83 *checksum
+= eep_data
[i
];
84 *checksum
= I210_TARGET_CHECKSUM
- *checksum
;
88 /** \brief This function can write the configuration space of the MACPHY
89 * For this purpose, the EEPROM interface is used. No direct access
90 * to the flash memory will be done. This function will update
91 * the checksum after a value was changed.
92 * @param *dev Pointer to the PCI device of this MACPHY
93 * @param address Address inside the flash where writing will start
94 * @param count Number of words (16 bit values) to write
95 * @param *buffer Pointer to the buffer where data to write is stored in
96 * @return void I210_NO_ERROR or an error code
98 static uint32_t write_flash(struct device
*dev
, uint32_t address
,
99 uint32_t count
, uint16_t *buffer
)
107 /* Get the BAR to memory mapped space */
108 bar
= pci_read_config32(dev
, 0x10);
109 if ((!bar
) || ((address
+ count
) > 0x40))
110 return I210_INVALID_PARAM
;
111 eepwr
= (uint32_t *)(bar
+ I210_REG_EEWRITE
);
112 eectrl
= (uint32_t *)(bar
+ I210_REG_EECTRL
);
113 /* Prior to start ensure flash interface is ready by checking DONE-bit */
114 if (wait_done(eepwr
, I210_DONE
))
115 return I210_NOT_READY
;
117 /* OK, interface is ready, we can use it now */
118 for (i
= 0; i
< count
; i
++) {
119 /* To start a write cycle write desired address in bits 12..2 */
120 /* and data to write in bits 31..16 into EEWRITE-register */
121 *eepwr
= ((((address
+ i
) << 2) & 0x1FFC) | (buffer
[i
] << 16));
122 /* Wait until write is done */
123 if (wait_done(eepwr
, I210_DONE
))
124 return I210_WRITE_ERROR
;
126 /* Since we have modified data, we need to update the checksum */
127 if (compute_checksum(dev
, &checksum
))
128 return I210_CHECKSUM_ERROR
;
129 *eepwr
= (0x3f << 2) | checksum
<< 16;
130 if (wait_done(eepwr
, I210_DONE
))
131 return I210_WRITE_ERROR
;
132 /* Up to now, desired data was written into shadowed RAM. We now need */
133 /* to perform a flash cycle to bring the shadowed RAM into flash. */
134 /* To start a flash cycle we need to set FLUPD and wait for FLDONE. */
135 *eectrl
= *eectrl
| I210_FLUPD
;
136 if (wait_done(eectrl
, I210_FLUDONE
))
137 return I210_FLASH_UPDATE_ERROR
;
141 /** \brief This function can read the MAC address out of the MACPHY
142 * @param *dev Pointer to the PCI device of this MACPHY
143 * @param *MACAdr Pointer to the buffer where to store read MAC address
144 * @return void I210_NO_ERROR or an error code
146 static uint32_t read_mac_adr(struct device
*dev
, uint8_t *mac_adr
)
149 if (!dev
|| !mac_adr
)
150 return I210_INVALID_PARAM
;
151 if (read_flash(dev
, 0, 3, adr
))
152 return I210_READ_ERROR
;
153 /* Copy the address into destination. This is done because of possible */
154 /* not matching alignment for destination to uint16_t boundary. */
155 memcpy(mac_adr
, (uint8_t *)adr
, 6);
159 /** \brief This function can write the MAC address to the MACPHY
160 * @param *dev Pointer to the PCI device of this MACPHY
161 * @param *MACAdr Pointer to the buffer where the desired MAC address is
162 * @return void I210_NO_ERROR or an error code
164 static uint32_t write_mac_adr(struct device
*dev
, uint8_t *mac_adr
)
167 if (!dev
|| !mac_adr
)
168 return I210_INVALID_PARAM
;
169 /* Copy desired address into a local buffer to avoid alignment issues */
170 memcpy((uint8_t *)adr
, mac_adr
, 6);
171 return write_flash(dev
, 0, 3, adr
);
174 /** \brief This function is the driver entry point for the init phase
175 * of the PCI bus allocator. It will program a MAC address
177 * @param *dev Pointer to the used PCI device
178 * @return void Nothing is given back
180 static void init(struct device
*dev
)
183 uint8_t adr_to_set
[6];
186 /*Check first whether there is a valid MAC address available */
187 status
= mainboard_get_mac_address(dev
, adr_to_set
);
188 if (status
!= CB_SUCCESS
) {
189 printk(BIOS_NOTICE
, "I210: Mainboard has no address, keep the one in MAC.\n");
192 /* Before we will write a new address, check the existing one */
193 if (read_mac_adr(dev
, cur_adr
)) {
194 printk(BIOS_ERR
, "I210: Not able to read MAC address.\n");
197 if (memcmp(cur_adr
, adr_to_set
, 6)) {
198 if (write_mac_adr(dev
, adr_to_set
))
199 printk(BIOS_ERR
, "I210: Error setting MAC address\n");
201 printk(BIOS_INFO
, "I210: MAC address changed.\n");
203 printk(BIOS_INFO
, "I210: MAC address is up to date.\n");
207 static void enable_bus_master(struct device
*dev
)
209 if (CONFIG(PCI_ALLOW_BUS_MASTER_ANY_DEVICE
))
210 pci_or_config16(dev
, PCI_COMMAND
, PCI_COMMAND_MASTER
);
213 static struct device_operations i210_ops
= {
214 .read_resources
= pci_dev_read_resources
,
215 .set_resources
= pci_dev_set_resources
,
216 .enable_resources
= pci_dev_enable_resources
,
218 .final
= enable_bus_master
,
221 static const unsigned short i210_device_ids
[] = { 0x1537, 0x1538, 0x1533, 0 };
223 static const struct pci_driver i210_driver __pci_driver
= {
225 .vendor
= PCI_VID_INTEL
,
226 .devices
= i210_device_ids
,