coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
superio.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 /*
4  * Generic driver for pretty much all known Standard Microsystems Corporation
5  * (SMSC) Super I/O chips.
6  *
7  * Datasheets are available from: http://www.smsc.com/main/datasheet.html
8  *
9  * Most of the SMSC Super I/O chips seem to be similar enough (for our
10  * purposes) so that we can handle them with a unified driver.
11  *
12  * So far only the ASUS A8000 has been tested on real hardware!
13  *
14  * The floppy disk controller, the parallel port, the serial ports, and the
15  * keyboard controller should work with all the chips. For the more advanced
16  * stuff (e.g. HWM, ACPI, SMBus) more work is probably required.
17  */
18 
19 #include <device/device.h>
20 #include <device/pnp.h>
21 #include <superio/conf_mode.h>
22 #include <console/console.h>
23 #include <pc80/keyboard.h>
24 
25 /* The following Super I/O chips are currently supported by this driver: */
26 #define LPC47M172 0x14
27 #define FDC37B80X 0x42 /* Same ID: FDC37M70X (a.k.a. FDC37M707) */
28 #define FDC37B78X 0x44
29 #define FDC37B72X 0x4c
30 #define FDC37M81X 0x4d
31 #define FDC37M60X 0x47
32 #define LPC47B27X 0x51 /* a.k.a. LPC47B272 */
33 #define LPC47U33X 0x54
34 #define LPC47M10X 0x59 /* Same ID: LPC47M112, LPC47M13X */
35 #define LPC47M15X 0x60 /* Same ID: LPC47M192 */
36 #define LPC47S45X 0x62
37 #define LPC47B397 0x6f
38 #define A8000 0x77 /* ASUS A8000, a rebranded DME1737(?) */
39 #define DME1737 0x78
40 #define SCH5504 0x79
41 #define SCH3112 0x7c
42 #define SCH3114 0x7d
43 #define SCH5307 0x81 /* Rebranded LPC47B397(?) */
44 #define SCH5027D 0x89
45 #define SCH4304 0x90 /* SCH4304, SCH4307 */
46 #define SCH5147 0xc1
47 
48 /* Register defines */
49 #define DEVICE_ID_REG 0x20 /* Device ID register */
50 #define DEVICE_REV_REG 0x21 /* Device revision register */
51 #define DEVICE_TEST7_REG 0x29 /* Device test 7 register */
52 
53 /* Static variables for the Super I/O device ID and revision. */
54 static int first_time = 1;
55 static u8 superio_id = 0;
56 static u8 superio_rev = 0;
57 
58 /**
59  * A list of all possible logical devices which may be supported by at least
60  * one of the Super I/O chips. These values are used as index into the
61  * logical_device_table[i].devs array(s).
62  *
63  * If you change this enum, you must also adapt the logical_device_table[]
64  * array and MAX_LOGICAL_DEVICES!
65  */
66 enum {
67  LD_FDC, /* Floppy disk controller */
68  LD_PP, /* Parallel port */
69  LD_SP1, /* Serial port 1 (COM1) */
70  LD_SP2, /* Serial port 2 (COM2) */
71  LD_RTC, /* Real-time clock */
72  LD_KBC, /* Keyboard controller */
73  LD_AUX, /* Auxiliary I/O */
74  LD_XBUS, /* X-Bus */
75  LD_HWM, /* Hardware monitor */
76  LD_GAME, /* Game port */
77  LD_PME, /* Power management events */
78  LD_MPU401, /* MPU-401 MIDI UART */
79  LD_RT, /* Runtime registers / security key registers */
80  LD_ACPI, /* ACPI */
81  LD_SMB, /* SMBus */
82 };
83 
84 /* Note: This value must match the number of items in the enum above! */
85 #define MAX_LOGICAL_DEVICES 15
86 
87 /**
88  * A table describing the logical devices which are present on the
89  * supported Super I/O chips.
90  *
91  * The first entry (superio_id) is the device ID of the Super I/O chip
92  * as stored in the (read-only) DEVICE_ID_REG register.
93  *
94  * The second entry (devs) is the list of logical device IDs which are
95  * present on that particular Super I/O chip. A value of -1 means the
96  * device is not present on that chip.
97  *
98  * Note: Do _not_ list chips with different name but same device ID twice!
99  * The result would be that the init code would be executed twice!
100  */
101 static const struct logical_devices {
104 } logical_device_table[] = {
105  /* Chip FDC PP SP1 SP2 RTC KBC AUX XBUS HWM GAME PME MPU RT ACPI SMB */
106  {LPC47M172,{0, 3, 4, 2, -1, 7, -1, -1, -1, -1, -1, -1, 10, -1, -1}},
107  {FDC37B80X,{0, 3, 4, 5, -1, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1}},
108  {FDC37B78X,{0, 3, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, 10, -1}},
109  {FDC37B72X,{0, 3, 4, 5, -1, 7, 8, -1, -1, -1, -1, -1, -1, 10, -1}},
110  {FDC37M81X,{0, 3, 4, 5, -1, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1}},
111  {FDC37M60X,{0, 3, 4, 5, -1, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1}},
112  {LPC47B27X,{0, 3, 4, 5, -1, 7, -1, -1, -1, 9, -1, 11, 10, -1, -1}},
113  {LPC47M10X,{0, 3, 4, 5, -1, 7, -1, -1, -1, 9, 10, 11, -1, -1, -1}},
114  {LPC47M15X,{0, 3, 4, 5, -1, 7, -1, -1, -1, 9, 10, 11, -1, -1, -1}},
115  {LPC47S45X,{0, 3, 4, 5, 6, 7, -1, 8, -1, -1, -1, -1, 10, -1, 11}},
116  {LPC47B397,{0, 3, 4, 5, -1, 7, -1, -1, 8, -1, -1, -1, 10, -1, -1}},
117  {LPC47U33X,{0, 3, 4, -1, -1, 7, -1, -1, -1, 9, 0, 5, 10, 0, 11}},
118  {A8000, {0, 3, 4, 5, -1, 7, -1, -1, -1, -1, -1, -1, 10, -1, -1}},
119  {DME1737, {0, 3, 4, 5, -1, 7, -1, -1, -1, -1, -1, -1, 10, -1, -1}},
120  {SCH5504, {0, 3, 4, 5, -1, 7, -1, -1, -1, -1, -1, -1, 10, -1, -1}},
121  {SCH3112, {0, 3, 4, 5, -1, 7, -1, -1, -1, -1, -1, -1, 10, -1, -1}},
122  {SCH3114, {0, 3, 4, 5, -1, 7, -1, -1, -1, -1, -1, -1, 10, -1, -1}},
123  {SCH5307, {0, 3, 4, 5, -1, 7, -1, -1, 8, -1, -1, -1, 10, -1, -1}},
124  {SCH5027D, {0, 3, 4, 5, -1, 7, -1, -1, -1, -1, -1, -1, 10, -1, 11}},
125  {SCH4304, {0, 3, 4, 5, -1, 7, -1, 11, -1, -1, -1, -1, 10, -1, -1}},
126  {SCH5147, {0, 3, 4, 5, -1, 7, -1, -1, -1, -1, -1, -1, 10, -1, -1}},
127 };
128 
129 /**
130  * Initialize those logical devices which need a special init.
131  *
132  * @param dev The device to use.
133  */
134 static void smsc_init(struct device *dev)
135 {
136  int i, ld;
137 
138  /* Do not initialize disabled devices. */
139  if (!dev->enabled)
140  return;
141 
142  /* Find the correct Super I/O. */
143  for (i = 0; i < ARRAY_SIZE(logical_device_table); i++)
145  break;
146 
147  /* If no Super I/O was found, return. */
149  return;
150 
151  /* A Super I/O was found, so initialize the respective device. */
152  ld = dev->path.pnp.device;
153  if (ld == logical_device_table[i].devs[LD_KBC]) {
155  }
156 }
157 
158 /** Standard device operations. */
159 static struct device_operations ops = {
161  .set_resources = pnp_set_resources,
162  .enable_resources = pnp_enable_resources,
163  .enable = pnp_alt_enable,
164  .init = smsc_init,
165  .ops_pnp_mode = &pnp_conf_mode_55_aa,
166 };
167 
168 /**
169  * TODO.
170  *
171  * This table should contain all possible entries for any of the supported
172  * Super I/O chips, even if some of them don't have the respective logical
173  * devices. That will be handled correctly by our code.
174  *
175  * The LD_FOO entries are device markers which tell you the type of the logical
176  * device (e.g. whether it's a floppy disk controller or a serial port etc.).
177  *
178  * Before using pnp_dev_info[] in pnp_enable_devices() these markers have
179  * to be replaced with the real logical device IDs of the respective
180  * Super I/O chip. This is done in enable_dev().
181  *
182  * TODO: FDC, PP, SP1, SP2, and KBC should work, the rest probably not (yet).
183  */
184 static struct pnp_info pnp_dev_info[] = {
185  { NULL, LD_FDC, PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, 0x07f8, },
186  { NULL, LD_PP, PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, 0x07f8, },
187  { NULL, LD_SP1, PNP_IO0 | PNP_IRQ0, 0x07f8, },
188  { NULL, LD_SP2, PNP_IO0 | PNP_IRQ0, 0x07f8, },
189  { NULL, LD_RTC, },
191  0x07ff, 0x07ff, },
192  { NULL, LD_AUX, },
193  { NULL, LD_XBUS, },
194  { NULL, LD_HWM, PNP_IO0, 0x07f0, },
195  { NULL, LD_GAME, },
196  { NULL, LD_PME, },
197  { NULL, LD_MPU401, },
198  { NULL, LD_RT, PNP_IO0, 0x0780, },
199  { NULL, LD_ACPI, },
200  { NULL, LD_SMB, },
201 };
202 
203 /**
204  * Enable the logical devices of the Super I/O chip.
205  *
206  * TODO: Think about how to handle the case when a mainboard has multiple
207  * Super I/O chips soldered on.
208  * TODO: Can this code be simplified a bit?
209  *
210  * @param dev The device to use.
211  */
212 static void enable_dev(struct device *dev)
213 {
214  int i, j, fn;
215  int tmp[MAX_LOGICAL_DEVICES];
216  u8 test7;
217 
218  if (first_time) {
219 
221 
222  /* Read the device ID and revision of the Super I/O chip. */
225 
226  /* TODO: Error handling? */
227 
228  printk(BIOS_INFO, "Found SMSC Super I/O (ID = 0x%02x, "
229  "rev = 0x%02x)\n", superio_id, superio_rev);
230  first_time = 0;
231 
232  if (superio_id == LPC47M172) {
233  /*
234  * Do not use the default logical device number but
235  * instead the standard SMSC registers set.
236  */
237 
238  /*
239  * TEST7 configuration register (0x29)
240  * Bit 0: LD_NUM (0 = new, 1 = std SMSC)
241  */
242  test7 = pnp_read_config(dev, DEVICE_TEST7_REG);
243  test7 |= (1 << 0);
244  pnp_write_config(dev, DEVICE_TEST7_REG, test7);
245  }
246 
248  }
249 
250  /* Find the correct Super I/O. */
251  for (i = 0; i < ARRAY_SIZE(logical_device_table); i++)
253  break;
254 
255  /* If no Super I/O was found, return. */
257  return;
258 
259  /* Temporarily save the LD_FOO values. */
260  for (j = 0; j < ARRAY_SIZE(pnp_dev_info); j++)
261  tmp[j] = pnp_dev_info[j].function;
262 
263  /*
264  * Replace the LD_FOO markers in pnp_dev_info[] with
265  * the real logical device IDs of this Super I/O chip.
266  */
267  for (j = 0; j < ARRAY_SIZE(pnp_dev_info); j++) {
268  fn = pnp_dev_info[j].function;
269  if (logical_device_table[i].devs[fn] != -1)
271  else
273  }
274 
275  /* Enable the specified devices (if present on the chip). */
277 
278  /* Restore LD_FOO values. */
279  for (j = 0; j < ARRAY_SIZE(pnp_dev_info); j++)
280  pnp_dev_info[j].function = tmp[j];
281 }
282 
284  CHIP_NAME("Various SMSC Super I/Os")
285  .enable_dev = enable_dev
286 };
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#define printk(level,...)
Definition: stdlib.h:16
void pnp_enter_conf_mode_55(struct device *dev)
Definition: conf_mode.c:10
const struct pnp_mode_ops pnp_conf_mode_55_aa
Definition: conf_mode.c:175
void pnp_exit_conf_mode_aa(struct device *dev)
Definition: conf_mode.c:45
#define CHIP_NAME(X)
Definition: device.h:32
uint8_t pc_keyboard_init(uint8_t probe_aux)
Definition: keyboard.c:229
#define NO_AUX_DEVICE
Definition: keyboard.h:6
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define PNP_IRQ1
Definition: pnp.h:48
#define PNP_SKIP_FUNCTION
Definition: pnp.h:39
#define PNP_DRQ0
Definition: pnp.h:49
#define PNP_IO1
Definition: pnp.h:43
#define PNP_IO0
Definition: pnp.h:42
#define PNP_IRQ0
Definition: pnp.h:47
void pnp_read_resources(struct device *dev)
Definition: pnp_device.c:114
void pnp_enable_devices(struct device *base_dev, struct device_operations *ops, unsigned int functions, struct pnp_info *info)
Definition: pnp_device.c:371
void pnp_set_resources(struct device *dev)
Definition: pnp_device.c:157
void pnp_alt_enable(struct device *dev)
Definition: pnp_device.c:191
u8 pnp_read_config(struct device *dev, u8 reg)
Definition: pnp_device.c:44
void pnp_write_config(struct device *dev, u8 reg, u8 value)
Definition: pnp_device.c:38
void pnp_enable_resources(struct device *dev)
Definition: pnp_device.c:173
#define DME1737
Definition: superio.c:39
#define DEVICE_ID_REG
Definition: superio.c:49
#define FDC37M81X
Definition: superio.c:30
#define SCH5147
Definition: superio.c:46
#define SCH5027D
Definition: superio.c:44
#define FDC37M60X
Definition: superio.c:31
static u8 superio_rev
Definition: superio.c:56
#define SCH5504
Definition: superio.c:40
static int first_time
Definition: superio.c:54
#define LPC47B397
Definition: superio.c:37
#define LPC47M15X
Definition: superio.c:35
#define SCH3112
Definition: superio.c:41
#define DEVICE_TEST7_REG
Definition: superio.c:51
#define FDC37B80X
Definition: superio.c:27
static void smsc_init(struct device *dev)
Initialize those logical devices which need a special init.
Definition: superio.c:134
#define SCH4304
Definition: superio.c:45
#define A8000
Definition: superio.c:38
#define SCH5307
Definition: superio.c:43
static void enable_dev(struct device *dev)
Enable the logical devices of the Super I/O chip.
Definition: superio.c:212
static struct device_operations ops
Standard device operations.
Definition: superio.c:159
static struct pnp_info pnp_dev_info[]
TODO.
Definition: superio.c:184
#define FDC37B72X
Definition: superio.c:29
#define LPC47S45X
Definition: superio.c:36
static const struct logical_devices logical_device_table[]
#define FDC37B78X
Definition: superio.c:28
#define SCH3114
Definition: superio.c:42
#define MAX_LOGICAL_DEVICES
Definition: superio.c:85
#define DEVICE_REV_REG
Definition: superio.c:50
struct chip_operations superio_smsc_smscsuperio_ops
Definition: superio.c:283
#define LPC47M10X
Definition: superio.c:34
#define LPC47M172
Definition: superio.c:26
@ LD_PME
Definition: superio.c:77
@ LD_GAME
Definition: superio.c:76
@ LD_ACPI
Definition: superio.c:80
@ LD_SP1
Definition: superio.c:69
@ LD_PP
Definition: superio.c:68
@ LD_KBC
Definition: superio.c:72
@ LD_MPU401
Definition: superio.c:78
@ LD_XBUS
Definition: superio.c:74
@ LD_AUX
Definition: superio.c:73
@ LD_SMB
Definition: superio.c:81
@ LD_RT
Definition: superio.c:79
@ LD_RTC
Definition: superio.c:71
@ LD_SP2
Definition: superio.c:70
@ LD_HWM
Definition: superio.c:75
@ LD_FDC
Definition: superio.c:67
#define LPC47B27X
Definition: superio.c:32
static u8 superio_id
Definition: superio.c:55
#define LPC47U33X
Definition: superio.c:33
#define NULL
Definition: stddef.h:19
uint8_t u8
Definition: stdint.h:45
void(* read_resources)(struct device *dev)
Definition: device.h:39
struct pnp_path pnp
Definition: path.h:117
Definition: device.h:107
struct device_path path
Definition: device.h:115
unsigned int enabled
Definition: device.h:122
A table describing the logical devices which are present on the supported Super I/O chips.
Definition: superio.c:101
int devs[MAX_LOGICAL_DEVICES]
Definition: superio.c:103
Definition: pnp.h:37
u16 function
Definition: pnp.h:40
unsigned int device
Definition: path.h:59