[flashrom] [PATCH] SMSC SuperI/O detection

Carl-Daniel Hailfinger c-d.hailfinger.devel.2006 at gmx.net
Tue May 8 00:59:36 CEST 2012


Add SMSC SuperI/O detection.
Avoid probing for SuperI/O at a port where we already know the SuperI/O.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>

Index: flashrom-smsc_superio_detect/it87spi.c
===================================================================
--- flashrom-smsc_superio_detect/it87spi.c	(Revision 1533)
+++ flashrom-smsc_superio_detect/it87spi.c	(Arbeitskopie)
@@ -80,6 +80,9 @@
 	s.vendor = SUPERIO_VENDOR_ITE;
 	for (; *i; i++) {
 		s.port = *i;
+		/* Skip if we already know the Super I/O on this port. */
+		if (superio_port_detected(s.port))
+			continue;
 		s.model = probe_id_ite(s.port);
 		switch (s.model >> 8) {
 		case 0x82:
Index: flashrom-smsc_superio_detect/internal.c
===================================================================
--- flashrom-smsc_superio_detect/internal.c	(Revision 1533)
+++ flashrom-smsc_superio_detect/internal.c	(Arbeitskopie)
@@ -107,7 +107,7 @@
 	 * at a given I/O port, do _not_ probe that port with the ITE probe.
 	 * This means SMSC probing must be done before ITE probing.
 	 */
-	//probe_superio_smsc();
+	probe_superio_smsc();
 	probe_superio_ite();
 }
 
@@ -116,6 +116,17 @@
 
 struct superio superios[SUPERIO_MAX_COUNT];
 
+/* Check if a Super I/O chip has already been detected on this port. */
+int superio_port_detected(uint16_t port)
+{
+	int i;
+
+	for (i = 0; i < superio_count; i++)
+		if (superios[i].port == port)
+			return 1;
+	return 0;
+}
+
 int register_superio(struct superio s)
 {
 	if (superio_count == SUPERIO_MAX_COUNT)
Index: flashrom-smsc_superio_detect/programmer.h
===================================================================
--- flashrom-smsc_superio_detect/programmer.h	(Revision 1533)
+++ flashrom-smsc_superio_detect/programmer.h	(Arbeitskopie)
@@ -247,6 +247,7 @@
 void w836xx_ext_enter(uint16_t port);
 void w836xx_ext_leave(uint16_t port);
 void probe_superio_winbond(void);
+void probe_superio_smsc(void);
 int it8705f_write_enable(uint8_t port);
 uint8_t sio_read(uint16_t port, uint8_t reg);
 void sio_write(uint16_t port, uint8_t reg, uint8_t data);
@@ -292,6 +293,7 @@
 #define SUPERIO_VENDOR_NONE	0x0
 #define SUPERIO_VENDOR_ITE	0x1
 #define SUPERIO_VENDOR_WINBOND	0x2
+#define SUPERIO_VENDOR_SMSC	0x3
 #endif
 #if NEED_PCI == 1
 struct pci_dev *pci_dev_find_filter(struct pci_filter filter);
@@ -308,6 +310,7 @@
 extern int force_boardenable;
 extern int force_boardmismatch;
 void probe_superio(void);
+int superio_port_detected(uint16_t port);
 int register_superio(struct superio s);
 extern enum chipbustype internal_buses_supported;
 int internal_init(void);
Index: flashrom-smsc_superio_detect/board_enable.c
===================================================================
--- flashrom-smsc_superio_detect/board_enable.c	(Revision 1533)
+++ flashrom-smsc_superio_detect/board_enable.c	(Arbeitskopie)
@@ -45,6 +45,13 @@
 	OUTB(0xAA, port);
 }
 
+void smsc_enter_conf_mode(uint16_t port)
+{
+	/* Most SMSC Super I/Os require only one 0x55, but the second one does not hurt. */
+	OUTB(0x55, port);
+	OUTB(0x55, port);
+}
+
 /* Generic Super I/O helper functions */
 uint8_t sio_read(uint16_t port, uint8_t reg)
 {
@@ -299,7 +306,10 @@
 	s.vendor = SUPERIO_VENDOR_WINBOND;
 	for (; *i; i++) {
 		s.port = *i;
-		/* If we're already in Super I/O config more, the W836xx enter sequence won't hurt. */
+		/* Skip if we already know the Super I/O on this port. */
+		if (superio_port_detected(s.port))
+			continue;
+		/* If we're already in Super I/O config mode, the W836xx enter sequence won't hurt. */
 		w836xx_ext_enter(s.port);
 		model = sio_read(s.port, 0x20);
 		/* No response, no point leaving the config mode. */
@@ -582,6 +592,63 @@
 	return 0;
 }
 
+#define SMSC_SUPERIO_PORT1	0x2e
+#define SMSC_SUPERIO_PORT2	0x4e
+
+enum smsc_id {
+	SMSC_LPC47N217_ID = 0x7a,
+	SMSC_LPC47N227_ID = 0x5a,
+	SMSC_LPC47N237_ID = 0x13,
+};
+
+void probe_superio_smsc(void)
+{
+	struct superio s = {};
+	uint16_t smsc_ports[] = {SMSC_SUPERIO_PORT1, SMSC_SUPERIO_PORT2, 0};
+	uint16_t *i = smsc_ports;
+	uint8_t model1;
+	uint8_t model2;
+
+	s.vendor = SUPERIO_VENDOR_SMSC;
+	for (; *i; i++) {
+		s.port = *i;
+		/* Skip if we already know the Super I/O on this port. */
+		if (superio_port_detected(s.port))
+			continue;
+		/* If we're already in Super I/O config mode, the SMSC enter sequence won't hurt. */
+		smsc_enter_conf_mode(s.port);
+		/* Older SMSC chips have their ID in register 0x0d. */
+		model1 = sio_read(s.port, 0x0d);
+		/* Newer SMSC chips have their ID in register 0x20. */
+		model2 = sio_read(s.port, 0x20);
+		/* No response, no point leaving the config mode. */
+		if ((model1 == 0xff) && (model2 == 0xff))
+			continue;
+		/* Try to leave config mode. If the ID register is still readable, it's not a SMSC chip. */
+		w836xx_ext_leave(s.port);
+		if ((model1 == sio_read(s.port, 0x0d)) && (model2 == sio_read(s.port, 0x20))) {
+			msg_pdbg("SMSC enter config mode worked or we were already in config mode. SMSC "
+				 "leave config mode had no effect.\n");
+			continue;
+		}
+		switch (model1) {
+		case SMSC_LPC47N217_ID:
+		case SMSC_LPC47N227_ID:
+		case SMSC_LPC47N237_ID:
+			/* Encode ID register location in the model. */
+			s.model = (0x0d << 8) | model1 ;
+			msg_pdbg("Found SMSC Super I/O, ID 0x%02x (reg %02x) on port 0x%x\n", s.model & 0xff,
+				 s.model >> 8, s.port);
+			register_superio(s);
+			continue;
+			break;
+		}
+		msg_pdbg("Found SMSC Super I/O, ID 0x%02x (reg 0x0d), ID 0x%02x (reg 0x20) on port 0x%x\n",
+			 model1, model2, s.port);
+		msg_pdbg("Not registering.\n");
+	}
+}
+
 /*
  * Suited for all boards with ITE IT8705F.
  * The SIS950 Super I/O probably requires a similar flash write enable.


-- 
http://www.hailfinger.org/





More information about the flashrom mailing list