|
11 | 11 | #include <linux/delay.h>
|
12 | 12 | #include <linux/device.h>
|
13 | 13 | #include <linux/dmi.h>
|
| 14 | +#include <linux/eeprom_93cx6.h> |
14 | 15 | #include <linux/interrupt.h>
|
15 | 16 | #include <linux/io.h>
|
16 | 17 | #include <linux/math.h>
|
|
191 | 192 | #define CTI_EE_OFF_XR17V35X_PORT_FLAGS 0x14 /* 1 word */
|
192 | 193 |
|
193 | 194 | #define CTI_EE_MASK_PORT_FLAGS_TYPE GENMASK(7, 0)
|
194 |
| -#define CTI_EE_MASK_OSC_FREQ_LOWER GENMASK(15, 0) |
195 |
| -#define CTI_EE_MASK_OSC_FREQ_UPPER GENMASK(31, 16) |
| 195 | +#define CTI_EE_MASK_OSC_FREQ GENMASK(31, 0) |
196 | 196 |
|
197 | 197 | #define CTI_FPGA_RS485_IO_REG 0x2008
|
198 | 198 | #define CTI_FPGA_CFG_INT_EN_REG 0x48
|
@@ -254,6 +254,7 @@ struct exar8250 {
|
254 | 254 | unsigned int nr;
|
255 | 255 | unsigned int osc_freq;
|
256 | 256 | struct exar8250_board *board;
|
| 257 | + struct eeprom_93cx6 eeprom; |
257 | 258 | void __iomem *virt;
|
258 | 259 | int line[];
|
259 | 260 | };
|
@@ -357,6 +358,39 @@ static u16 exar_ee_read(struct exar8250 *priv, u8 ee_addr)
|
357 | 358 | return data;
|
358 | 359 | }
|
359 | 360 |
|
| 361 | +static void exar_eeprom_93cx6_reg_read(struct eeprom_93cx6 *eeprom) |
| 362 | +{ |
| 363 | + struct exar8250 *priv = eeprom->data; |
| 364 | + u8 regb = exar_read_reg(priv, UART_EXAR_REGB); |
| 365 | + |
| 366 | + /* EECK and EECS always read 0 from REGB so only set EEDO */ |
| 367 | + eeprom->reg_data_out = regb & UART_EXAR_REGB_EEDO; |
| 368 | +} |
| 369 | + |
| 370 | +static void exar_eeprom_93cx6_reg_write(struct eeprom_93cx6 *eeprom) |
| 371 | +{ |
| 372 | + struct exar8250 *priv = eeprom->data; |
| 373 | + u8 regb = 0; |
| 374 | + |
| 375 | + if (eeprom->reg_data_in) |
| 376 | + regb |= UART_EXAR_REGB_EEDI; |
| 377 | + if (eeprom->reg_data_clock) |
| 378 | + regb |= UART_EXAR_REGB_EECK; |
| 379 | + if (eeprom->reg_chip_select) |
| 380 | + regb |= UART_EXAR_REGB_EECS; |
| 381 | + |
| 382 | + exar_write_reg(priv, UART_EXAR_REGB, regb); |
| 383 | +} |
| 384 | + |
| 385 | +static void exar_eeprom_init(struct exar8250 *priv) |
| 386 | +{ |
| 387 | + priv->eeprom.data = priv; |
| 388 | + priv->eeprom.register_read = exar_eeprom_93cx6_reg_read; |
| 389 | + priv->eeprom.register_write = exar_eeprom_93cx6_reg_write; |
| 390 | + priv->eeprom.width = PCI_EEPROM_WIDTH_93C46; |
| 391 | + priv->eeprom.quirks |= PCI_EEPROM_QUIRK_EXTRA_READ_CYCLE; |
| 392 | +} |
| 393 | + |
360 | 394 | /**
|
361 | 395 | * exar_mpio_config_output() - Configure an Exar MPIO as an output
|
362 | 396 | * @priv: Device's private structure
|
@@ -698,20 +732,16 @@ static int cti_plx_int_enable(struct exar8250 *priv)
|
698 | 732 | */
|
699 | 733 | static int cti_read_osc_freq(struct exar8250 *priv, u8 eeprom_offset)
|
700 | 734 | {
|
701 |
| - u16 lower_word; |
702 |
| - u16 upper_word; |
| 735 | + __le16 ee_words[2]; |
| 736 | + u32 osc_freq; |
703 | 737 |
|
704 |
| - lower_word = exar_ee_read(priv, eeprom_offset); |
705 |
| - // Check if EEPROM word was blank |
706 |
| - if (lower_word == 0xFFFF) |
707 |
| - return -EIO; |
| 738 | + eeprom_93cx6_multiread(&priv->eeprom, eeprom_offset, ee_words, ARRAY_SIZE(ee_words)); |
708 | 739 |
|
709 |
| - upper_word = exar_ee_read(priv, (eeprom_offset + 1)); |
710 |
| - if (upper_word == 0xFFFF) |
| 740 | + osc_freq = le16_to_cpu(ee_words[0]) | (le16_to_cpu(ee_words[1]) << 16); |
| 741 | + if (osc_freq == CTI_EE_MASK_OSC_FREQ) |
711 | 742 | return -EIO;
|
712 | 743 |
|
713 |
| - return FIELD_PREP(CTI_EE_MASK_OSC_FREQ_LOWER, lower_word) | |
714 |
| - FIELD_PREP(CTI_EE_MASK_OSC_FREQ_UPPER, upper_word); |
| 744 | + return osc_freq; |
715 | 745 | }
|
716 | 746 |
|
717 | 747 | /**
|
@@ -835,7 +865,7 @@ static enum cti_port_type cti_get_port_type_xr17v35x(struct exar8250 *priv,
|
835 | 865 | u8 offset;
|
836 | 866 |
|
837 | 867 | offset = CTI_EE_OFF_XR17V35X_PORT_FLAGS + port_num;
|
838 |
| - port_flags = exar_ee_read(priv, offset); |
| 868 | + eeprom_93cx6_read(&priv->eeprom, offset, &port_flags); |
839 | 869 |
|
840 | 870 | port_type = FIELD_GET(CTI_EE_MASK_PORT_FLAGS_TYPE, port_flags);
|
841 | 871 | if (CTI_PORT_TYPE_VALID(port_type))
|
@@ -1553,6 +1583,8 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
|
1553 | 1583 | if (rc)
|
1554 | 1584 | return rc;
|
1555 | 1585 |
|
| 1586 | + exar_eeprom_init(priv); |
| 1587 | + |
1556 | 1588 | for (i = 0; i < nr_ports && i < maxnr; i++) {
|
1557 | 1589 | rc = board->setup(priv, pcidev, &uart, i);
|
1558 | 1590 | if (rc) {
|
|
0 commit comments