diff options
author | Hans de Goede <hdegoede@redhat.com> | 2015-12-11 10:32:17 -0500 |
---|---|---|
committer | Kishon Vijay Abraham I <kishon@ti.com> | 2015-12-20 04:51:38 -0500 |
commit | 68dbc2ce77bbe18a0475a497f4d6adde7c5d0b0c (patch) | |
tree | cdc1800f333aac977c805d7dde94358287efba3e /drivers/phy | |
parent | 75f072f9eab72e10a45886d84a9a762b1c65071d (diff) |
phy-sun4i-usb: Use of_match_node to get model specific config data
Use of_match_node instead of calling of_device_is_compatible a ton of
times to get model specific config data.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Diffstat (limited to 'drivers/phy')
-rw-r--r-- | drivers/phy/phy-sun4i-usb.c | 121 |
1 files changed, 79 insertions, 42 deletions
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index b12964b70625..35b1fa3b71fe 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/mutex.h> | 32 | #include <linux/mutex.h> |
33 | #include <linux/of.h> | 33 | #include <linux/of.h> |
34 | #include <linux/of_address.h> | 34 | #include <linux/of_address.h> |
35 | #include <linux/of_device.h> | ||
35 | #include <linux/of_gpio.h> | 36 | #include <linux/of_gpio.h> |
36 | #include <linux/phy/phy.h> | 37 | #include <linux/phy/phy.h> |
37 | #include <linux/phy/phy-sun4i-usb.h> | 38 | #include <linux/phy/phy-sun4i-usb.h> |
@@ -88,12 +89,23 @@ | |||
88 | #define DEBOUNCE_TIME msecs_to_jiffies(50) | 89 | #define DEBOUNCE_TIME msecs_to_jiffies(50) |
89 | #define POLL_TIME msecs_to_jiffies(250) | 90 | #define POLL_TIME msecs_to_jiffies(250) |
90 | 91 | ||
92 | enum sun4i_usb_phy_type { | ||
93 | sun4i_a10_phy, | ||
94 | sun8i_a33_phy, | ||
95 | }; | ||
96 | |||
97 | struct sun4i_usb_phy_cfg { | ||
98 | int num_phys; | ||
99 | enum sun4i_usb_phy_type type; | ||
100 | u32 disc_thresh; | ||
101 | u8 phyctl_offset; | ||
102 | bool dedicated_clocks; | ||
103 | }; | ||
104 | |||
91 | struct sun4i_usb_phy_data { | 105 | struct sun4i_usb_phy_data { |
92 | void __iomem *base; | 106 | void __iomem *base; |
107 | const struct sun4i_usb_phy_cfg *cfg; | ||
93 | struct mutex mutex; | 108 | struct mutex mutex; |
94 | int num_phys; | ||
95 | u32 disc_thresh; | ||
96 | bool has_a33_phyctl; | ||
97 | struct sun4i_usb_phy { | 109 | struct sun4i_usb_phy { |
98 | struct phy *phy; | 110 | struct phy *phy; |
99 | void __iomem *pmu; | 111 | void __iomem *pmu; |
@@ -159,17 +171,14 @@ static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data, | |||
159 | { | 171 | { |
160 | struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy); | 172 | struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy); |
161 | u32 temp, usbc_bit = BIT(phy->index * 2); | 173 | u32 temp, usbc_bit = BIT(phy->index * 2); |
162 | void *phyctl; | 174 | void *phyctl = phy_data->base + phy_data->cfg->phyctl_offset; |
163 | int i; | 175 | int i; |
164 | 176 | ||
165 | mutex_lock(&phy_data->mutex); | 177 | mutex_lock(&phy_data->mutex); |
166 | 178 | ||
167 | if (phy_data->has_a33_phyctl) { | 179 | if (phy_data->cfg->type == sun8i_a33_phy) { |
168 | phyctl = phy_data->base + REG_PHYCTL_A33; | ||
169 | /* A33 needs us to set phyctl to 0 explicitly */ | 180 | /* A33 needs us to set phyctl to 0 explicitly */ |
170 | writel(0, phyctl); | 181 | writel(0, phyctl); |
171 | } else { | ||
172 | phyctl = phy_data->base + REG_PHYCTL_A10; | ||
173 | } | 182 | } |
174 | 183 | ||
175 | for (i = 0; i < len; i++) { | 184 | for (i = 0; i < len; i++) { |
@@ -249,7 +258,8 @@ static int sun4i_usb_phy_init(struct phy *_phy) | |||
249 | sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5); | 258 | sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5); |
250 | 259 | ||
251 | /* Disconnect threshold adjustment */ | 260 | /* Disconnect threshold adjustment */ |
252 | sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, data->disc_thresh, 2); | 261 | sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, |
262 | data->cfg->disc_thresh, 2); | ||
253 | 263 | ||
254 | sun4i_usb_phy_passby(phy, 1); | 264 | sun4i_usb_phy_passby(phy, 1); |
255 | 265 | ||
@@ -476,7 +486,7 @@ static struct phy *sun4i_usb_phy_xlate(struct device *dev, | |||
476 | { | 486 | { |
477 | struct sun4i_usb_phy_data *data = dev_get_drvdata(dev); | 487 | struct sun4i_usb_phy_data *data = dev_get_drvdata(dev); |
478 | 488 | ||
479 | if (args->args[0] >= data->num_phys) | 489 | if (args->args[0] >= data->cfg->num_phys) |
480 | return ERR_PTR(-ENODEV); | 490 | return ERR_PTR(-ENODEV); |
481 | 491 | ||
482 | return data->phys[args->args[0]].phy; | 492 | return data->phys[args->args[0]].phy; |
@@ -511,7 +521,6 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) | |||
511 | struct device *dev = &pdev->dev; | 521 | struct device *dev = &pdev->dev; |
512 | struct device_node *np = dev->of_node; | 522 | struct device_node *np = dev->of_node; |
513 | struct phy_provider *phy_provider; | 523 | struct phy_provider *phy_provider; |
514 | bool dedicated_clocks; | ||
515 | struct resource *res; | 524 | struct resource *res; |
516 | int i, ret; | 525 | int i, ret; |
517 | 526 | ||
@@ -522,29 +531,9 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) | |||
522 | mutex_init(&data->mutex); | 531 | mutex_init(&data->mutex); |
523 | INIT_DELAYED_WORK(&data->detect, sun4i_usb_phy0_id_vbus_det_scan); | 532 | INIT_DELAYED_WORK(&data->detect, sun4i_usb_phy0_id_vbus_det_scan); |
524 | dev_set_drvdata(dev, data); | 533 | dev_set_drvdata(dev, data); |
525 | 534 | data->cfg = of_device_get_match_data(dev); | |
526 | if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy") || | 535 | if (!data->cfg) |
527 | of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy") || | 536 | return -EINVAL; |
528 | of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy")) | ||
529 | data->num_phys = 2; | ||
530 | else | ||
531 | data->num_phys = 3; | ||
532 | |||
533 | if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy") || | ||
534 | of_device_is_compatible(np, "allwinner,sun7i-a20-usb-phy")) | ||
535 | data->disc_thresh = 2; | ||
536 | else | ||
537 | data->disc_thresh = 3; | ||
538 | |||
539 | if (of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy") || | ||
540 | of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy") || | ||
541 | of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy")) | ||
542 | dedicated_clocks = true; | ||
543 | else | ||
544 | dedicated_clocks = false; | ||
545 | |||
546 | if (of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy")) | ||
547 | data->has_a33_phyctl = true; | ||
548 | 537 | ||
549 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl"); | 538 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl"); |
550 | data->base = devm_ioremap_resource(dev, res); | 539 | data->base = devm_ioremap_resource(dev, res); |
@@ -590,7 +579,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) | |||
590 | } | 579 | } |
591 | } | 580 | } |
592 | 581 | ||
593 | for (i = 0; i < data->num_phys; i++) { | 582 | for (i = 0; i < data->cfg->num_phys; i++) { |
594 | struct sun4i_usb_phy *phy = data->phys + i; | 583 | struct sun4i_usb_phy *phy = data->phys + i; |
595 | char name[16]; | 584 | char name[16]; |
596 | 585 | ||
@@ -602,7 +591,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) | |||
602 | phy->vbus = NULL; | 591 | phy->vbus = NULL; |
603 | } | 592 | } |
604 | 593 | ||
605 | if (dedicated_clocks) | 594 | if (data->cfg->dedicated_clocks) |
606 | snprintf(name, sizeof(name), "usb%d_phy", i); | 595 | snprintf(name, sizeof(name), "usb%d_phy", i); |
607 | else | 596 | else |
608 | strlcpy(name, "usb_phy", sizeof(name)); | 597 | strlcpy(name, "usb_phy", sizeof(name)); |
@@ -689,13 +678,61 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) | |||
689 | return 0; | 678 | return 0; |
690 | } | 679 | } |
691 | 680 | ||
681 | static const struct sun4i_usb_phy_cfg sun4i_a10_cfg = { | ||
682 | .num_phys = 3, | ||
683 | .type = sun4i_a10_phy, | ||
684 | .disc_thresh = 3, | ||
685 | .phyctl_offset = REG_PHYCTL_A10, | ||
686 | .dedicated_clocks = false, | ||
687 | }; | ||
688 | |||
689 | static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = { | ||
690 | .num_phys = 2, | ||
691 | .type = sun4i_a10_phy, | ||
692 | .disc_thresh = 2, | ||
693 | .phyctl_offset = REG_PHYCTL_A10, | ||
694 | .dedicated_clocks = false, | ||
695 | }; | ||
696 | |||
697 | static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = { | ||
698 | .num_phys = 3, | ||
699 | .type = sun4i_a10_phy, | ||
700 | .disc_thresh = 3, | ||
701 | .phyctl_offset = REG_PHYCTL_A10, | ||
702 | .dedicated_clocks = true, | ||
703 | }; | ||
704 | |||
705 | static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = { | ||
706 | .num_phys = 3, | ||
707 | .type = sun4i_a10_phy, | ||
708 | .disc_thresh = 2, | ||
709 | .phyctl_offset = REG_PHYCTL_A10, | ||
710 | .dedicated_clocks = false, | ||
711 | }; | ||
712 | |||
713 | static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = { | ||
714 | .num_phys = 2, | ||
715 | .type = sun4i_a10_phy, | ||
716 | .disc_thresh = 3, | ||
717 | .phyctl_offset = REG_PHYCTL_A10, | ||
718 | .dedicated_clocks = true, | ||
719 | }; | ||
720 | |||
721 | static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = { | ||
722 | .num_phys = 2, | ||
723 | .type = sun8i_a33_phy, | ||
724 | .disc_thresh = 3, | ||
725 | .phyctl_offset = REG_PHYCTL_A33, | ||
726 | .dedicated_clocks = true, | ||
727 | }; | ||
728 | |||
692 | static const struct of_device_id sun4i_usb_phy_of_match[] = { | 729 | static const struct of_device_id sun4i_usb_phy_of_match[] = { |
693 | { .compatible = "allwinner,sun4i-a10-usb-phy" }, | 730 | { .compatible = "allwinner,sun4i-a10-usb-phy", .data = &sun4i_a10_cfg }, |
694 | { .compatible = "allwinner,sun5i-a13-usb-phy" }, | 731 | { .compatible = "allwinner,sun5i-a13-usb-phy", .data = &sun5i_a13_cfg }, |
695 | { .compatible = "allwinner,sun6i-a31-usb-phy" }, | 732 | { .compatible = "allwinner,sun6i-a31-usb-phy", .data = &sun6i_a31_cfg }, |
696 | { .compatible = "allwinner,sun7i-a20-usb-phy" }, | 733 | { .compatible = "allwinner,sun7i-a20-usb-phy", .data = &sun7i_a20_cfg }, |
697 | { .compatible = "allwinner,sun8i-a23-usb-phy" }, | 734 | { .compatible = "allwinner,sun8i-a23-usb-phy", .data = &sun8i_a23_cfg }, |
698 | { .compatible = "allwinner,sun8i-a33-usb-phy" }, | 735 | { .compatible = "allwinner,sun8i-a33-usb-phy", .data = &sun8i_a33_cfg }, |
699 | { }, | 736 | { }, |
700 | }; | 737 | }; |
701 | MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match); | 738 | MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match); |