.. | .. |
---|
12 | 12 | |
---|
13 | 13 | #include <linux/delay.h> |
---|
14 | 14 | #include <linux/gpio/consumer.h> |
---|
| 15 | +#include <linux/gpio/driver.h> |
---|
15 | 16 | #include <linux/i2c.h> |
---|
16 | 17 | #include <linux/module.h> |
---|
17 | 18 | #include <linux/nls.h> |
---|
18 | 19 | #include <linux/of_device.h> |
---|
| 20 | +#include <linux/regulator/consumer.h> |
---|
19 | 21 | #include <linux/slab.h> |
---|
20 | 22 | |
---|
21 | 23 | /* Internal Register Set Addresses & Default Values acc. to DS00001692C */ |
---|
.. | .. |
---|
25 | 27 | |
---|
26 | 28 | #define USB251XB_ADDR_PRODUCT_ID_LSB 0x02 |
---|
27 | 29 | #define USB251XB_ADDR_PRODUCT_ID_MSB 0x03 |
---|
28 | | -#define USB251XB_DEF_PRODUCT_ID_12 0x2512 /* USB2512B/12Bi */ |
---|
29 | | -#define USB251XB_DEF_PRODUCT_ID_13 0x2513 /* USB2513B/13Bi */ |
---|
30 | | -#define USB251XB_DEF_PRODUCT_ID_14 0x2514 /* USB2514B/14Bi */ |
---|
31 | | -#define USB251XB_DEF_PRODUCT_ID_17 0x2517 /* USB2517/17i */ |
---|
32 | 30 | |
---|
33 | 31 | #define USB251XB_ADDR_DEVICE_ID_LSB 0x04 |
---|
34 | 32 | #define USB251XB_ADDR_DEVICE_ID_MSB 0x05 |
---|
.. | .. |
---|
73 | 71 | |
---|
74 | 72 | #define USB251XB_ADDR_PRODUCT_STRING_LEN 0x14 |
---|
75 | 73 | #define USB251XB_ADDR_PRODUCT_STRING 0x54 |
---|
76 | | -#define USB251XB_DEF_PRODUCT_STRING "USB251xB/xBi/7i" |
---|
77 | 74 | |
---|
78 | 75 | #define USB251XB_ADDR_SERIAL_STRING_LEN 0x15 |
---|
79 | 76 | #define USB251XB_ADDR_SERIAL_STRING 0x92 |
---|
.. | .. |
---|
115 | 112 | struct usb251xb { |
---|
116 | 113 | struct device *dev; |
---|
117 | 114 | struct i2c_client *i2c; |
---|
| 115 | + struct regulator *vdd; |
---|
118 | 116 | u8 skip_config; |
---|
119 | 117 | struct gpio_desc *gpio_reset; |
---|
120 | 118 | u16 vendor_id; |
---|
.. | .. |
---|
156 | 154 | bool led_support; |
---|
157 | 155 | bool bat_support; |
---|
158 | 156 | char product_str[USB251XB_STRING_BUFSIZE / 2]; /* ASCII string */ |
---|
| 157 | +}; |
---|
| 158 | + |
---|
| 159 | +static const struct usb251xb_data usb2422_data = { |
---|
| 160 | + .product_id = 0x2422, |
---|
| 161 | + .port_cnt = 2, |
---|
| 162 | + .led_support = false, |
---|
| 163 | + .bat_support = true, |
---|
| 164 | + .product_str = "USB2422", |
---|
159 | 165 | }; |
---|
160 | 166 | |
---|
161 | 167 | static const struct usb251xb_data usb2512b_data = { |
---|
.. | .. |
---|
222 | 228 | .product_str = "USB2517i", |
---|
223 | 229 | }; |
---|
224 | 230 | |
---|
225 | | -static void usb251xb_reset(struct usb251xb *hub, int state) |
---|
| 231 | +#ifdef CONFIG_GPIOLIB |
---|
| 232 | +static int usb251xb_check_dev_children(struct device *dev, void *child) |
---|
| 233 | +{ |
---|
| 234 | + if (dev->type == &i2c_adapter_type) { |
---|
| 235 | + return device_for_each_child(dev, child, |
---|
| 236 | + usb251xb_check_dev_children); |
---|
| 237 | + } |
---|
| 238 | + |
---|
| 239 | + return (dev == child); |
---|
| 240 | +} |
---|
| 241 | + |
---|
| 242 | +static int usb251x_check_gpio_chip(struct usb251xb *hub) |
---|
| 243 | +{ |
---|
| 244 | + struct gpio_chip *gc = gpiod_to_chip(hub->gpio_reset); |
---|
| 245 | + struct i2c_adapter *adap = hub->i2c->adapter; |
---|
| 246 | + int ret; |
---|
| 247 | + |
---|
| 248 | + if (!hub->gpio_reset) |
---|
| 249 | + return 0; |
---|
| 250 | + |
---|
| 251 | + if (!gc) |
---|
| 252 | + return -EINVAL; |
---|
| 253 | + |
---|
| 254 | + ret = usb251xb_check_dev_children(&adap->dev, gc->parent); |
---|
| 255 | + if (ret) { |
---|
| 256 | + dev_err(hub->dev, "Reset GPIO chip is at the same i2c-bus\n"); |
---|
| 257 | + return -EINVAL; |
---|
| 258 | + } |
---|
| 259 | + |
---|
| 260 | + return 0; |
---|
| 261 | +} |
---|
| 262 | +#else |
---|
| 263 | +static int usb251x_check_gpio_chip(struct usb251xb *hub) |
---|
| 264 | +{ |
---|
| 265 | + return 0; |
---|
| 266 | +} |
---|
| 267 | +#endif |
---|
| 268 | + |
---|
| 269 | +static void usb251xb_reset(struct usb251xb *hub) |
---|
226 | 270 | { |
---|
227 | 271 | if (!hub->gpio_reset) |
---|
228 | 272 | return; |
---|
229 | 273 | |
---|
230 | | - gpiod_set_value_cansleep(hub->gpio_reset, state); |
---|
| 274 | + i2c_lock_bus(hub->i2c->adapter, I2C_LOCK_SEGMENT); |
---|
| 275 | + |
---|
| 276 | + gpiod_set_value_cansleep(hub->gpio_reset, 1); |
---|
| 277 | + usleep_range(1, 10); /* >=1us RESET_N asserted */ |
---|
| 278 | + gpiod_set_value_cansleep(hub->gpio_reset, 0); |
---|
231 | 279 | |
---|
232 | 280 | /* wait for hub recovery/stabilization */ |
---|
233 | | - if (!state) |
---|
234 | | - usleep_range(500, 750); /* >=500us at power on */ |
---|
235 | | - else |
---|
236 | | - usleep_range(1, 10); /* >=1us at power down */ |
---|
| 281 | + usleep_range(500, 750); /* >=500us after RESET_N deasserted */ |
---|
| 282 | + |
---|
| 283 | + i2c_unlock_bus(hub->i2c->adapter, I2C_LOCK_SEGMENT); |
---|
237 | 284 | } |
---|
238 | 285 | |
---|
239 | 286 | static int usb251xb_connect(struct usb251xb *hub) |
---|
.. | .. |
---|
249 | 296 | i2c_wb[0] = 0x01; |
---|
250 | 297 | i2c_wb[1] = USB251XB_STATUS_COMMAND_ATTACH; |
---|
251 | 298 | |
---|
252 | | - usb251xb_reset(hub, 0); |
---|
| 299 | + usb251xb_reset(hub); |
---|
253 | 300 | |
---|
254 | 301 | err = i2c_smbus_write_i2c_block_data(hub->i2c, |
---|
255 | 302 | USB251XB_ADDR_STATUS_COMMAND, 2, i2c_wb); |
---|
.. | .. |
---|
299 | 346 | i2c_wb[USB251XB_ADDR_PORT_MAP_7] = hub->port_map7; |
---|
300 | 347 | i2c_wb[USB251XB_ADDR_STATUS_COMMAND] = USB251XB_STATUS_COMMAND_ATTACH; |
---|
301 | 348 | |
---|
302 | | - usb251xb_reset(hub, 0); |
---|
| 349 | + usb251xb_reset(hub); |
---|
303 | 350 | |
---|
304 | 351 | /* write registers */ |
---|
305 | 352 | for (i = 0; i < (USB251XB_I2C_REG_SZ / USB251XB_I2C_WRITE_SZ); i++) { |
---|
.. | .. |
---|
331 | 378 | } |
---|
332 | 379 | |
---|
333 | 380 | #ifdef CONFIG_OF |
---|
| 381 | +static void usb251xb_get_ports_field(struct usb251xb *hub, |
---|
| 382 | + const char *prop_name, u8 port_cnt, |
---|
| 383 | + bool ds_only, u8 *fld) |
---|
| 384 | +{ |
---|
| 385 | + struct device *dev = hub->dev; |
---|
| 386 | + struct property *prop; |
---|
| 387 | + const __be32 *p; |
---|
| 388 | + u32 port; |
---|
| 389 | + |
---|
| 390 | + of_property_for_each_u32(dev->of_node, prop_name, prop, p, port) { |
---|
| 391 | + if ((port >= ds_only ? 1 : 0) && (port <= port_cnt)) |
---|
| 392 | + *fld |= BIT(port); |
---|
| 393 | + else |
---|
| 394 | + dev_warn(dev, "port %u doesn't exist\n", port); |
---|
| 395 | + } |
---|
| 396 | +} |
---|
| 397 | + |
---|
334 | 398 | static int usb251xb_get_ofdata(struct usb251xb *hub, |
---|
335 | 399 | struct usb251xb_data *data) |
---|
336 | 400 | { |
---|
337 | 401 | struct device *dev = hub->dev; |
---|
338 | 402 | struct device_node *np = dev->of_node; |
---|
339 | | - int len, err, i; |
---|
| 403 | + int len, err; |
---|
340 | 404 | u32 property_u32 = 0; |
---|
341 | | - const u32 *cproperty_u32; |
---|
342 | 405 | const char *cproperty_char; |
---|
343 | 406 | char str[USB251XB_STRING_BUFSIZE / 2]; |
---|
344 | 407 | |
---|
.. | .. |
---|
442 | 505 | hub->conf_data3 |= BIT(0); |
---|
443 | 506 | |
---|
444 | 507 | hub->non_rem_dev = USB251XB_DEF_NON_REMOVABLE_DEVICES; |
---|
445 | | - cproperty_u32 = of_get_property(np, "non-removable-ports", &len); |
---|
446 | | - if (cproperty_u32 && (len / sizeof(u32)) > 0) { |
---|
447 | | - for (i = 0; i < len / sizeof(u32); i++) { |
---|
448 | | - u32 port = be32_to_cpu(cproperty_u32[i]); |
---|
449 | | - |
---|
450 | | - if ((port >= 1) && (port <= data->port_cnt)) |
---|
451 | | - hub->non_rem_dev |= BIT(port); |
---|
452 | | - else |
---|
453 | | - dev_warn(dev, "NRD port %u doesn't exist\n", |
---|
454 | | - port); |
---|
455 | | - } |
---|
456 | | - } |
---|
| 508 | + usb251xb_get_ports_field(hub, "non-removable-ports", data->port_cnt, |
---|
| 509 | + true, &hub->non_rem_dev); |
---|
457 | 510 | |
---|
458 | 511 | hub->port_disable_sp = USB251XB_DEF_PORT_DISABLE_SELF; |
---|
459 | | - cproperty_u32 = of_get_property(np, "sp-disabled-ports", &len); |
---|
460 | | - if (cproperty_u32 && (len / sizeof(u32)) > 0) { |
---|
461 | | - for (i = 0; i < len / sizeof(u32); i++) { |
---|
462 | | - u32 port = be32_to_cpu(cproperty_u32[i]); |
---|
463 | | - |
---|
464 | | - if ((port >= 1) && (port <= data->port_cnt)) |
---|
465 | | - hub->port_disable_sp |= BIT(port); |
---|
466 | | - else |
---|
467 | | - dev_warn(dev, "PDS port %u doesn't exist\n", |
---|
468 | | - port); |
---|
469 | | - } |
---|
470 | | - } |
---|
| 512 | + usb251xb_get_ports_field(hub, "sp-disabled-ports", data->port_cnt, |
---|
| 513 | + true, &hub->port_disable_sp); |
---|
471 | 514 | |
---|
472 | 515 | hub->port_disable_bp = USB251XB_DEF_PORT_DISABLE_BUS; |
---|
473 | | - cproperty_u32 = of_get_property(np, "bp-disabled-ports", &len); |
---|
474 | | - if (cproperty_u32 && (len / sizeof(u32)) > 0) { |
---|
475 | | - for (i = 0; i < len / sizeof(u32); i++) { |
---|
476 | | - u32 port = be32_to_cpu(cproperty_u32[i]); |
---|
477 | | - |
---|
478 | | - if ((port >= 1) && (port <= data->port_cnt)) |
---|
479 | | - hub->port_disable_bp |= BIT(port); |
---|
480 | | - else |
---|
481 | | - dev_warn(dev, "PDB port %u doesn't exist\n", |
---|
482 | | - port); |
---|
483 | | - } |
---|
484 | | - } |
---|
| 516 | + usb251xb_get_ports_field(hub, "bp-disabled-ports", data->port_cnt, |
---|
| 517 | + true, &hub->port_disable_bp); |
---|
485 | 518 | |
---|
486 | 519 | hub->max_power_sp = USB251XB_DEF_MAX_POWER_SELF; |
---|
487 | 520 | if (!of_property_read_u32(np, "sp-max-total-current-microamp", |
---|
.. | .. |
---|
539 | 572 | (wchar_t *)hub->serial, |
---|
540 | 573 | USB251XB_STRING_BUFSIZE); |
---|
541 | 574 | |
---|
| 575 | + /* |
---|
| 576 | + * The datasheet documents the register as 'Port Swap' but in real the |
---|
| 577 | + * register controls the USB DP/DM signal swapping for each port. |
---|
| 578 | + */ |
---|
| 579 | + hub->port_swap = USB251XB_DEF_PORT_SWAP; |
---|
| 580 | + usb251xb_get_ports_field(hub, "swap-dx-lanes", data->port_cnt, |
---|
| 581 | + false, &hub->port_swap); |
---|
| 582 | + |
---|
542 | 583 | /* The following parameters are currently not exposed to devicetree, but |
---|
543 | 584 | * may be as soon as needed. |
---|
544 | 585 | */ |
---|
.. | .. |
---|
546 | 587 | hub->boost_up = USB251XB_DEF_BOOST_UP; |
---|
547 | 588 | hub->boost_57 = USB251XB_DEF_BOOST_57; |
---|
548 | 589 | hub->boost_14 = USB251XB_DEF_BOOST_14; |
---|
549 | | - hub->port_swap = USB251XB_DEF_PORT_SWAP; |
---|
550 | 590 | hub->port_map12 = USB251XB_DEF_PORT_MAP_12; |
---|
551 | 591 | hub->port_map34 = USB251XB_DEF_PORT_MAP_34; |
---|
552 | 592 | hub->port_map56 = USB251XB_DEF_PORT_MAP_56; |
---|
.. | .. |
---|
557 | 597 | |
---|
558 | 598 | static const struct of_device_id usb251xb_of_match[] = { |
---|
559 | 599 | { |
---|
| 600 | + .compatible = "microchip,usb2422", |
---|
| 601 | + .data = &usb2422_data, |
---|
| 602 | + }, { |
---|
560 | 603 | .compatible = "microchip,usb2512b", |
---|
561 | 604 | .data = &usb2512b_data, |
---|
562 | 605 | }, { |
---|
.. | .. |
---|
593 | 636 | } |
---|
594 | 637 | #endif /* CONFIG_OF */ |
---|
595 | 638 | |
---|
| 639 | +static void usb251xb_regulator_disable_action(void *data) |
---|
| 640 | +{ |
---|
| 641 | + struct usb251xb *hub = data; |
---|
| 642 | + |
---|
| 643 | + regulator_disable(hub->vdd); |
---|
| 644 | +} |
---|
| 645 | + |
---|
596 | 646 | static int usb251xb_probe(struct usb251xb *hub) |
---|
597 | 647 | { |
---|
598 | 648 | struct device *dev = hub->dev; |
---|
.. | .. |
---|
609 | 659 | return err; |
---|
610 | 660 | } |
---|
611 | 661 | } |
---|
| 662 | + |
---|
| 663 | + /* |
---|
| 664 | + * usb251x SMBus-slave SCL lane is muxed with CFG_SEL0 pin. So if anyone |
---|
| 665 | + * tries to work with the bus at the moment the hub reset is released, |
---|
| 666 | + * it may cause an invalid config being latched by usb251x. Particularly |
---|
| 667 | + * one of the config modes makes the hub loading a default registers |
---|
| 668 | + * value without SMBus-slave interface activation. If the hub |
---|
| 669 | + * accidentally gets this mode, this will cause the driver SMBus- |
---|
| 670 | + * functions failure. Normally we could just lock the SMBus-segment the |
---|
| 671 | + * hub i2c-interface resides for the device-specific reset timing. But |
---|
| 672 | + * the GPIO controller, which is used to handle the hub reset, might be |
---|
| 673 | + * placed at the same i2c-bus segment. In this case an error should be |
---|
| 674 | + * returned since we can't safely use the GPIO controller to clear the |
---|
| 675 | + * reset state (it may affect the hub configuration) and we can't lock |
---|
| 676 | + * the i2c-bus segment (it will cause a deadlock). |
---|
| 677 | + */ |
---|
| 678 | + err = usb251x_check_gpio_chip(hub); |
---|
| 679 | + if (err) |
---|
| 680 | + return err; |
---|
| 681 | + |
---|
| 682 | + hub->vdd = devm_regulator_get(dev, "vdd"); |
---|
| 683 | + if (IS_ERR(hub->vdd)) |
---|
| 684 | + return PTR_ERR(hub->vdd); |
---|
| 685 | + |
---|
| 686 | + err = regulator_enable(hub->vdd); |
---|
| 687 | + if (err) |
---|
| 688 | + return err; |
---|
| 689 | + |
---|
| 690 | + err = devm_add_action_or_reset(dev, |
---|
| 691 | + usb251xb_regulator_disable_action, hub); |
---|
| 692 | + if (err) |
---|
| 693 | + return err; |
---|
612 | 694 | |
---|
613 | 695 | err = usb251xb_connect(hub); |
---|
614 | 696 | if (err) { |
---|
.. | .. |
---|
637 | 719 | return usb251xb_probe(hub); |
---|
638 | 720 | } |
---|
639 | 721 | |
---|
| 722 | +static int __maybe_unused usb251xb_suspend(struct device *dev) |
---|
| 723 | +{ |
---|
| 724 | + struct i2c_client *client = to_i2c_client(dev); |
---|
| 725 | + struct usb251xb *hub = i2c_get_clientdata(client); |
---|
| 726 | + |
---|
| 727 | + return regulator_disable(hub->vdd); |
---|
| 728 | +} |
---|
| 729 | + |
---|
| 730 | +static int __maybe_unused usb251xb_resume(struct device *dev) |
---|
| 731 | +{ |
---|
| 732 | + struct i2c_client *client = to_i2c_client(dev); |
---|
| 733 | + struct usb251xb *hub = i2c_get_clientdata(client); |
---|
| 734 | + int err; |
---|
| 735 | + |
---|
| 736 | + err = regulator_enable(hub->vdd); |
---|
| 737 | + if (err) |
---|
| 738 | + return err; |
---|
| 739 | + |
---|
| 740 | + return usb251xb_connect(hub); |
---|
| 741 | +} |
---|
| 742 | + |
---|
| 743 | +static SIMPLE_DEV_PM_OPS(usb251xb_pm_ops, usb251xb_suspend, usb251xb_resume); |
---|
| 744 | + |
---|
640 | 745 | static const struct i2c_device_id usb251xb_id[] = { |
---|
| 746 | + { "usb2422", 0 }, |
---|
641 | 747 | { "usb2512b", 0 }, |
---|
642 | 748 | { "usb2512bi", 0 }, |
---|
643 | 749 | { "usb2513b", 0 }, |
---|
.. | .. |
---|
654 | 760 | .driver = { |
---|
655 | 761 | .name = DRIVER_NAME, |
---|
656 | 762 | .of_match_table = of_match_ptr(usb251xb_of_match), |
---|
| 763 | + .pm = &usb251xb_pm_ops, |
---|
657 | 764 | }, |
---|
658 | 765 | .probe = usb251xb_i2c_probe, |
---|
659 | 766 | .id_table = usb251xb_id, |
---|