@@ -113,7 +113,51 @@ static struct gpiod_lookup_table asustor_fs6700_gpio_leds_lookup = {
113113 },
114114};
115115
116- static struct gpiod_lookup_table asustor_6700_gpio_leds_lookup = {
116+ static struct gpiod_lookup_table asustor_as6702_gpio_leds_lookup = {
117+ .dev_id = "leds-gpio" ,
118+ .table = {
119+ // 0: AS6702T and AS5402T don't have a front panel to illuminate
120+ // 1: they don't have a LCD either
121+ GPIO_LOOKUP_IDX (GPIO_IT87 , 56 , NULL , 2 , GPIO_ACTIVE_LOW ), // blue:power
122+ GPIO_LOOKUP_IDX (GPIO_IT87 , 8 , NULL , 3 , GPIO_ACTIVE_LOW ), // red:power
123+ GPIO_LOOKUP_IDX (GPIO_IT87 , 31 , NULL , 4 , GPIO_ACTIVE_LOW ), // green:status
124+ GPIO_LOOKUP_IDX (GPIO_IT87 , 49 , NULL , 5 , GPIO_ACTIVE_LOW ), // red:status
125+ // 6
126+ GPIO_LOOKUP_IDX (GPIO_IT87 , 21 , NULL , 7 , GPIO_ACTIVE_LOW ), // green:usb
127+ GPIO_LOOKUP_IDX (GPIO_IT87 , 55 , NULL , 8 , GPIO_ACTIVE_HIGH ), // blue:lan
128+ GPIO_LOOKUP_IDX (GPIO_IT87 , 12 , NULL , 9 , GPIO_ACTIVE_HIGH ), // sata1:green:disk
129+ GPIO_LOOKUP_IDX (GPIO_IT87 , 13 , NULL , 10 , GPIO_ACTIVE_LOW ), // sata1:red:disk
130+ GPIO_LOOKUP_IDX (GPIO_IT87 , 46 , NULL , 11 , GPIO_ACTIVE_HIGH ), // sata2:green:disk
131+ GPIO_LOOKUP_IDX (GPIO_IT87 , 47 , NULL , 12 , GPIO_ACTIVE_LOW ), // sata2:red:disk
132+ {}
133+ },
134+ };
135+
136+ static struct gpiod_lookup_table asustor_as6704_gpio_leds_lookup = {
137+ .dev_id = "leds-gpio" ,
138+ .table = {
139+ GPIO_LOOKUP_IDX (GPIO_IT87 , 29 , NULL , 0 , GPIO_ACTIVE_HIGH ), // power:front_panel
140+ GPIO_LOOKUP_IDX (GPIO_IT87 , 59 , NULL , 1 , GPIO_ACTIVE_HIGH ), // power:lcd
141+ GPIO_LOOKUP_IDX (GPIO_IT87 , 56 , NULL , 2 , GPIO_ACTIVE_LOW ), // blue:power
142+ GPIO_LOOKUP_IDX (GPIO_IT87 , 8 , NULL , 3 , GPIO_ACTIVE_LOW ), // red:power
143+ GPIO_LOOKUP_IDX (GPIO_IT87 , 31 , NULL , 4 , GPIO_ACTIVE_LOW ), // green:status
144+ GPIO_LOOKUP_IDX (GPIO_IT87 , 49 , NULL , 5 , GPIO_ACTIVE_LOW ), // red:status
145+ // 6
146+ GPIO_LOOKUP_IDX (GPIO_IT87 , 21 , NULL , 7 , GPIO_ACTIVE_LOW ), // green:usb
147+ GPIO_LOOKUP_IDX (GPIO_IT87 , 55 , NULL , 8 , GPIO_ACTIVE_HIGH ), // blue:lan
148+ GPIO_LOOKUP_IDX (GPIO_IT87 , 12 , NULL , 9 , GPIO_ACTIVE_HIGH ), // sata1:green:disk
149+ GPIO_LOOKUP_IDX (GPIO_IT87 , 13 , NULL , 10 , GPIO_ACTIVE_LOW ), // sata1:red:disk
150+ GPIO_LOOKUP_IDX (GPIO_IT87 , 46 , NULL , 11 , GPIO_ACTIVE_HIGH ), // sata2:green:disk
151+ GPIO_LOOKUP_IDX (GPIO_IT87 , 47 , NULL , 12 , GPIO_ACTIVE_LOW ), // sata2:red:disk
152+ GPIO_LOOKUP_IDX (GPIO_IT87 , 51 , NULL , 13 , GPIO_ACTIVE_HIGH ), // sata3:green:disk
153+ GPIO_LOOKUP_IDX (GPIO_IT87 , 52 , NULL , 14 , GPIO_ACTIVE_LOW ), // sata3:red:disk
154+ GPIO_LOOKUP_IDX (GPIO_IT87 , 63 , NULL , 15 , GPIO_ACTIVE_HIGH ), // sata4:green:disk
155+ GPIO_LOOKUP_IDX (GPIO_IT87 , 48 , NULL , 16 , GPIO_ACTIVE_LOW ), // sata4:red:disk
156+ {}
157+ },
158+ };
159+
160+ static struct gpiod_lookup_table asustor_as6706_gpio_leds_lookup = {
117161 .dev_id = "leds-gpio" ,
118162 .table = {
119163 GPIO_LOOKUP_IDX (GPIO_IT87 , 29 , NULL , 0 , GPIO_ACTIVE_HIGH ), // power:front_panel
@@ -263,44 +307,111 @@ struct asustor_driver_data {
263307 struct gpiod_lookup_table * keys ;
264308};
265309
266- #define VALID_OVERRIDE_NAMES "AS6xx, AS61xx, AS66xx, AS67xx, FS67xx"
310+ #define VALID_OVERRIDE_NAMES \
311+ "AS6xx, AS61xx, AS66xx, AS6702, AS6704, AS6706, FS6706, FS6712"
267312
268313// NOTE: if you add another device here, update VALID_OVERRIDE_NAMES accordingly!
269314
270- static struct asustor_driver_data asustor_fs6700_driver_data = {
271- .name = "FS67xx" ,
272- // FS67xx needs to match PCI devices because it has the same DMI data as *A*S67xx
315+ /*
316+ * Unfortunately, AS67xx and FS67xx can't be told apart by DMI, they all identify as
317+ * "Intel Corporation" - "Jasper Lake Client Platform", so we need to match PCI devices.
318+ *
319+ * How to tell AS67xx and FS6xx apart:
320+ *
321+ * only AS6702T/AS5402T has [8086:4dd3] Intel Corporation Jasper Lake SATA AHCI Controller
322+ * (only [AF]S67xx: [8086:4dc8] Intel Corporation Jasper Lake HD Audio
323+ * - but for now I think AS670xT vs AS540xT doesn't matter. Not sure if AS5404T has this; AS5402T doesn't)
324+ *
325+ * only AS6704T has [1b21:1164] ASMedia Technology Inc. ASM1164 Serial ATA AHCI Controller
326+ * - TODO: does AS5404T also use this? until disproven, I assume it does
327+ * only AS6706T has [1b21:1166] ASMedia Technology Inc. ASM1166 Serial ATA Controller
328+ *
329+ * only FS6712X has [1b21:2806] ASMedia Technology Inc. ASM2806 4-Port PCIe x2 Gen3 Packet Switch
330+ * (it doesn't have any SATA controller)
331+ * FS6706T does not have any SATA controller and no ASMedia PCIe packet switch either
332+ */
333+
334+ static struct asustor_driver_data asustor_as6702_driver_data = {
335+ .name = "AS6702" ,
336+ .pci_matches = {
337+ // SATA controller [0106]: Intel Corporation Jasper Lake SATA AHCI Controller [8086:4dd3] (rev 01)
338+ // Both AS6702T and AS5402T use this SATA controller (the other devices don't)
339+ { 0x8086 , 0x4dd3 , 1 , 1 }
340+ },
341+ .leds = & asustor_as6702_gpio_leds_lookup ,
342+ .keys = & asustor_6100_gpio_keys_lookup ,
343+ };
344+
345+ static struct asustor_driver_data asustor_as6704_driver_data = {
346+ .name = "AS6704" ,
347+ .pci_matches = {
348+ // SATA controller: ASMedia Technology Inc. ASM1164 Serial ATA AHCI Controller [1b21:1164] (rev 02)
349+ // This SATA controller is used by AS6704T, and hopefully by AS5404T as well, but
350+ // not by any of the other AS67xx or FS67xx devices
351+ { 0x1b21 , 0x1164 , 1 , 1 }
352+ },
353+ .leds = & asustor_as6704_gpio_leds_lookup ,
354+ .keys = & asustor_6100_gpio_keys_lookup ,
355+ };
356+
357+ static struct asustor_driver_data asustor_as6706_driver_data = {
358+ .name = "AS6706" ,
359+ .pci_matches = {
360+ // SATA controller [0106]: ASMedia Technology Inc. ASM1166 Serial ATA Controller [1b21:1166] (rev 02)
361+ // only used by AS6706T; there (currently?) is no AS5406T
362+ { 0x1b21 , 0x1166 , 1 , 1 }
363+ // (BTW, AS6706T also has 5x "ASM2812 6-Port PCIe x4 Gen3 Packet Switch" [1b21:2812],
364+ // which thankfully is NOT the same one that FS6712 uses. Also it allows replacing the
365+ // m.2 NVME slots with a 10Gbit NIC, could be that then the packet switch goes away, IDK)
366+ },
367+ .leds = & asustor_as6706_gpio_leds_lookup ,
368+ .keys = & asustor_6100_gpio_keys_lookup ,
369+ };
370+
371+ static struct asustor_driver_data asustor_fs6712_driver_data = {
372+ .name = "FS6712" ,
273373 .pci_matches = {
274374 // PCI bridge: ASMedia Technology Inc. ASM2806 4-Port PCIe x2 Gen3 Packet Switch (rev 01)
275- // FS6712X seems to have 15 of these, no idea about FS6706T (so I keep min_count at 1)
276- // currently the upper limit doesn't matter so I just use DEVICE_COUNT_MAX
375+ // apparently only FS6712X uses this - 15 of those turn up in lspci, at least if
376+ // all m.2 NVME slots have a SSD installed. I guess it's safest to match that at least
377+ // one of these exist; upper limit doesn't matter, so just use DEVICE_COUNT_MAX
277378 { 0x1b21 , 0x2806 , 1 , DEVICE_COUNT_MAX },
278379 },
279380 .leds = & asustor_fs6700_gpio_leds_lookup ,
280381 .keys = & asustor_fs6700_gpio_keys_lookup ,
281382};
282383
283- static struct asustor_driver_data asustor_6700_driver_data = {
284- .name = "AS67xx" ,
285- // AS67xx needs to match PCI devices because it has the same DMI data as *F*S67xx
384+ static struct asustor_driver_data asustor_fs6706_driver_data = {
385+ .name = "FS6706" ,
286386 .pci_matches = {
287- // PCI bridge: ASMedia Technology Inc. ASM2806 4-Port PCIe x2 Gen3 Packet Switch (rev 01)
288- // *F*S67xx seems to use these, *A*S67xx doesn't, so expect 0
289- // (BTW, AS6706T has 5x "ASM2812 6-Port PCIe x4 Gen3 Packet Switch" [1b21:2812], I hope *F*S6706T doesn't)
387+ // FS6706T doesn't have that ASMedia PCI bridge / PCIe Packet switch
290388 { 0x1b21 , 0x2806 , 0 , 0 },
389+ // .. it doesn't have any of the SATA controllers either
390+ { 0x8086 , 0x4dd3 , 0 , 0 }, // .. not the Intel one used by AS6702T/AS5402T
391+ { 0x1b21 , 0x1164 , 0 , 0 }, // .. neither the ASMedia one used by AS6704T
392+ { 0x1b21 , 0x1166 , 0 , 0 }, // .. nor the ASMedia one used by AS6706T
291393 },
292- .leds = & asustor_6700_gpio_leds_lookup ,
293- .keys = & asustor_6100_gpio_keys_lookup ,
394+ .leds = & asustor_fs6700_gpio_leds_lookup ,
395+ .keys = & asustor_fs6700_gpio_keys_lookup ,
294396};
295397
398+ /*
399+ * It currently looks like the older systems are easier to tell apart, at least if one doesn't insist
400+ * on detecting the 2 vs 4 vs 6 drives versions (I only did this for AS67xx because I had to do the
401+ * advanced detection anyway)
402+ */
403+
296404static struct asustor_driver_data asustor_6600_driver_data = {
297405 // NOTE: This is (currently?) the same as for AS6700
298406 // because it seems to use the same GPIO numbers,
299407 // but listed extra for the different name
300408 .name = "AS66xx" ,
301409 // This (and the remaining systems) don't need to match PCI devices to be detected,
302410 // so they're not set here (and thus initialized to all-zero)
303- .leds = & asustor_6700_gpio_leds_lookup ,
411+
412+ // the LED GPIOs are the same as in AS67xx, so use the one from AS6704 which should work for
413+ // both AS6602T and AS6604T (an AS66xx with more than 4 drives doesn't seem to exist)
414+ .leds = & asustor_as6704_gpio_leds_lookup ,
304415 .keys = & asustor_6100_gpio_keys_lookup ,
305416};
306417
@@ -316,34 +427,61 @@ static struct asustor_driver_data asustor_600_driver_data = {
316427 .keys = & asustor_600_gpio_keys_lookup ,
317428};
318429
319- // NOTE: Don't use this table with dmi_first_match(), because it has two entries that
320- // match the same (AS67xx and FS67xx). find_matching_asustor_system() handles
430+ // NOTE: Don't use this table with dmi_first_match(), because it has several entries that
431+ // match the same (for AS67xx and FS67xx). find_matching_asustor_system() handles
321432// that by also matching PCI devices from asustor_driver_data::pci_matches.
322433// This table only exists in this form (instead of just using an array of
323434// asustor_driver_data) for MODULE_DEVICE_TABLE().
324435static const struct dmi_system_id asustor_systems [] = {
325436 // NOTE: each entry in this table must have its own unique asustor_driver_data
326437 // (having a unique .name) set as .driver_data
438+
439+ // The following devices all use the same DMI matches and are actually told apart by
440+ // our custom matching logic in find_matching_asustor_system() also takes
441+ // driver_data->pci_matches[] into account.
442+ // See also the bigger comment above about AS67xx vs FS67xx
443+ {
444+ // NOTE: This not only matches (and works with) AS6702T (Lockerstor Gen2),
445+ // but also AS5402T (Nimbustor Gen2)
446+ .matches = {
447+ DMI_EXACT_MATCH (DMI_SYS_VENDOR , "Intel Corporation" ),
448+ DMI_EXACT_MATCH (DMI_PRODUCT_NAME , "Jasper Lake Client Platform" ),
449+ },
450+ .driver_data = & asustor_as6702_driver_data ,
451+ },
452+ {
453+ // NOTE: This not only matches (and works with) AS6704T (Lockerstor Gen2),
454+ // but (hopefully!) also AS5404T (Nimbustor Gen2)
455+ .matches = {
456+ DMI_EXACT_MATCH (DMI_SYS_VENDOR , "Intel Corporation" ),
457+ DMI_EXACT_MATCH (DMI_PRODUCT_NAME , "Jasper Lake Client Platform" ),
458+ },
459+ .driver_data = & asustor_as6704_driver_data ,
460+ },
327461 {
328- // NOTE: yes, this is the same DMI match as the next entry, because just by DMI,
329- // FS67xx and AS67xx can't be told apart. But our custom matching logic
330- // in find_matching_asustor_system() also takes driver_data->pci_matches[]
331- // into account, so that should be ok.
332462 .matches = {
333463 DMI_EXACT_MATCH (DMI_SYS_VENDOR , "Intel Corporation" ),
334464 DMI_EXACT_MATCH (DMI_PRODUCT_NAME , "Jasper Lake Client Platform" ),
335465 },
336- .driver_data = & asustor_fs6700_driver_data ,
466+ .driver_data = & asustor_as6706_driver_data ,
337467 },
468+ // *F*S67xx:
338469 {
339- // NOTE: This not only matches (and works with) AS670xT (Lockerstor Gen2),
340- // but also AS540xT (Nimbustor Gen2)
341470 .matches = {
342471 DMI_EXACT_MATCH (DMI_SYS_VENDOR , "Intel Corporation" ),
343472 DMI_EXACT_MATCH (DMI_PRODUCT_NAME , "Jasper Lake Client Platform" ),
344473 },
345- .driver_data = & asustor_6700_driver_data ,
474+ .driver_data = & asustor_fs6706_driver_data ,
346475 },
476+ {
477+ .matches = {
478+ DMI_EXACT_MATCH (DMI_SYS_VENDOR , "Intel Corporation" ),
479+ DMI_EXACT_MATCH (DMI_PRODUCT_NAME , "Jasper Lake Client Platform" ),
480+ },
481+ .driver_data = & asustor_fs6712_driver_data ,
482+ },
483+
484+ // older devices can be matched only by DMI
347485 {
348486 .matches = {
349487 DMI_EXACT_MATCH (DMI_SYS_VENDOR , "Insyde" ),
0 commit comments