aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2017-12-14 05:27:47 -0500
committerDavid S. Miller <davem@davemloft.net>2017-12-15 13:23:22 -0500
commit259c8618b0099bfa613997b43857752167cddc20 (patch)
tree5a9e78ff7b6afd08433d7affa62740e5b88ec84e
parent512dc8fed99a361e6caf185b14292ab0a60ebd2f (diff)
sfp: add sff module support
Add support for SFF modules, which are soldered down SFP modules. These have a different phys_id value, and also have the present and rate select signals omitted compared with their socketed counter-parts. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/phy/sfp.c78
-rw-r--r--include/linux/sfp.h1
2 files changed, 65 insertions, 14 deletions
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index 9dfc1c4c954f..96511557eb2c 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -98,12 +98,18 @@ static const enum gpiod_flags gpio_flags[] = {
98 98
99static DEFINE_MUTEX(sfp_mutex); 99static DEFINE_MUTEX(sfp_mutex);
100 100
101struct sff_data {
102 unsigned int gpios;
103 bool (*module_supported)(const struct sfp_eeprom_id *id);
104};
105
101struct sfp { 106struct sfp {
102 struct device *dev; 107 struct device *dev;
103 struct i2c_adapter *i2c; 108 struct i2c_adapter *i2c;
104 struct mii_bus *i2c_mii; 109 struct mii_bus *i2c_mii;
105 struct sfp_bus *sfp_bus; 110 struct sfp_bus *sfp_bus;
106 struct phy_device *mod_phy; 111 struct phy_device *mod_phy;
112 const struct sff_data *type;
107 113
108 unsigned int (*get_state)(struct sfp *); 114 unsigned int (*get_state)(struct sfp *);
109 void (*set_state)(struct sfp *, unsigned int); 115 void (*set_state)(struct sfp *, unsigned int);
@@ -123,6 +129,36 @@ struct sfp {
123 struct sfp_eeprom_id id; 129 struct sfp_eeprom_id id;
124}; 130};
125 131
132static bool sff_module_supported(const struct sfp_eeprom_id *id)
133{
134 return id->base.phys_id == SFP_PHYS_ID_SFF &&
135 id->base.phys_ext_id == SFP_PHYS_EXT_ID_SFP;
136}
137
138static const struct sff_data sff_data = {
139 .gpios = SFP_F_LOS | SFP_F_TX_FAULT | SFP_F_TX_DISABLE,
140 .module_supported = sff_module_supported,
141};
142
143static bool sfp_module_supported(const struct sfp_eeprom_id *id)
144{
145 return id->base.phys_id == SFP_PHYS_ID_SFP &&
146 id->base.phys_ext_id == SFP_PHYS_EXT_ID_SFP;
147}
148
149static const struct sff_data sfp_data = {
150 .gpios = SFP_F_PRESENT | SFP_F_LOS | SFP_F_TX_FAULT |
151 SFP_F_TX_DISABLE | SFP_F_RATE_SELECT,
152 .module_supported = sfp_module_supported,
153};
154
155static const struct of_device_id sfp_of_match[] = {
156 { .compatible = "sff,sff", .data = &sff_data, },
157 { .compatible = "sff,sfp", .data = &sfp_data, },
158 { },
159};
160MODULE_DEVICE_TABLE(of, sfp_of_match);
161
126static unsigned long poll_jiffies; 162static unsigned long poll_jiffies;
127 163
128static unsigned int sfp_gpio_get_state(struct sfp *sfp) 164static unsigned int sfp_gpio_get_state(struct sfp *sfp)
@@ -141,6 +177,11 @@ static unsigned int sfp_gpio_get_state(struct sfp *sfp)
141 return state; 177 return state;
142} 178}
143 179
180static unsigned int sff_gpio_get_state(struct sfp *sfp)
181{
182 return sfp_gpio_get_state(sfp) | SFP_F_PRESENT;
183}
184
144static void sfp_gpio_set_state(struct sfp *sfp, unsigned int state) 185static void sfp_gpio_set_state(struct sfp *sfp, unsigned int state)
145{ 186{
146 if (state & SFP_F_PRESENT) { 187 if (state & SFP_F_PRESENT) {
@@ -479,10 +520,10 @@ static int sfp_sm_mod_probe(struct sfp *sfp)
479 dev_info(sfp->dev, "module %s %s rev %s sn %s dc %s\n", 520 dev_info(sfp->dev, "module %s %s rev %s sn %s dc %s\n",
480 vendor, part, rev, sn, date); 521 vendor, part, rev, sn, date);
481 522
482 /* We only support SFP modules, not the legacy GBIC modules. */ 523 /* Check whether we support this module */
483 if (sfp->id.base.phys_id != SFP_PHYS_ID_SFP || 524 if (!sfp->type->module_supported(&sfp->id)) {
484 sfp->id.base.phys_ext_id != SFP_PHYS_EXT_ID_SFP) { 525 dev_err(sfp->dev,
485 dev_err(sfp->dev, "module is not SFP - phys id 0x%02x 0x%02x\n", 526 "module is not supported - phys id 0x%02x 0x%02x\n",
486 sfp->id.base.phys_id, sfp->id.base.phys_ext_id); 527 sfp->id.base.phys_id, sfp->id.base.phys_ext_id);
487 return -EINVAL; 528 return -EINVAL;
488 } 529 }
@@ -801,6 +842,7 @@ static void sfp_cleanup(void *data)
801 842
802static int sfp_probe(struct platform_device *pdev) 843static int sfp_probe(struct platform_device *pdev)
803{ 844{
845 const struct sff_data *sff;
804 struct sfp *sfp; 846 struct sfp *sfp;
805 bool poll = false; 847 bool poll = false;
806 int irq, err, i; 848 int irq, err, i;
@@ -815,10 +857,19 @@ static int sfp_probe(struct platform_device *pdev)
815 if (err < 0) 857 if (err < 0)
816 return err; 858 return err;
817 859
860 sff = sfp->type = &sfp_data;
861
818 if (pdev->dev.of_node) { 862 if (pdev->dev.of_node) {
819 struct device_node *node = pdev->dev.of_node; 863 struct device_node *node = pdev->dev.of_node;
864 const struct of_device_id *id;
820 struct device_node *np; 865 struct device_node *np;
821 866
867 id = of_match_node(sfp_of_match, node);
868 if (WARN_ON(!id))
869 return -EINVAL;
870
871 sff = sfp->type = id->data;
872
822 np = of_parse_phandle(node, "i2c-bus", 0); 873 np = of_parse_phandle(node, "i2c-bus", 0);
823 if (np) { 874 if (np) {
824 struct i2c_adapter *i2c; 875 struct i2c_adapter *i2c;
@@ -834,17 +885,22 @@ static int sfp_probe(struct platform_device *pdev)
834 return err; 885 return err;
835 } 886 }
836 } 887 }
888 }
837 889
838 for (i = 0; i < GPIO_MAX; i++) { 890 for (i = 0; i < GPIO_MAX; i++)
891 if (sff->gpios & BIT(i)) {
839 sfp->gpio[i] = devm_gpiod_get_optional(sfp->dev, 892 sfp->gpio[i] = devm_gpiod_get_optional(sfp->dev,
840 gpio_of_names[i], gpio_flags[i]); 893 gpio_of_names[i], gpio_flags[i]);
841 if (IS_ERR(sfp->gpio[i])) 894 if (IS_ERR(sfp->gpio[i]))
842 return PTR_ERR(sfp->gpio[i]); 895 return PTR_ERR(sfp->gpio[i]);
843 } 896 }
844 897
845 sfp->get_state = sfp_gpio_get_state; 898 sfp->get_state = sfp_gpio_get_state;
846 sfp->set_state = sfp_gpio_set_state; 899 sfp->set_state = sfp_gpio_set_state;
847 } 900
901 /* Modules that have no detect signal are always present */
902 if (!(sfp->gpio[GPIO_MODDEF0]))
903 sfp->get_state = sff_gpio_get_state;
848 904
849 sfp->sfp_bus = sfp_register_socket(sfp->dev, sfp, &sfp_module_ops); 905 sfp->sfp_bus = sfp_register_socket(sfp->dev, sfp, &sfp_module_ops);
850 if (!sfp->sfp_bus) 906 if (!sfp->sfp_bus)
@@ -899,12 +955,6 @@ static int sfp_remove(struct platform_device *pdev)
899 return 0; 955 return 0;
900} 956}
901 957
902static const struct of_device_id sfp_of_match[] = {
903 { .compatible = "sff,sfp", },
904 { },
905};
906MODULE_DEVICE_TABLE(of, sfp_of_match);
907
908static struct platform_driver sfp_driver = { 958static struct platform_driver sfp_driver = {
909 .probe = sfp_probe, 959 .probe = sfp_probe,
910 .remove = sfp_remove, 960 .remove = sfp_remove,
diff --git a/include/linux/sfp.h b/include/linux/sfp.h
index 47ea32d3e816..0c5c5f6ae1ec 100644
--- a/include/linux/sfp.h
+++ b/include/linux/sfp.h
@@ -231,6 +231,7 @@ enum {
231 SFP_SFF8472_COMPLIANCE = 0x5e, 231 SFP_SFF8472_COMPLIANCE = 0x5e,
232 SFP_CC_EXT = 0x5f, 232 SFP_CC_EXT = 0x5f,
233 233
234 SFP_PHYS_ID_SFF = 0x02,
234 SFP_PHYS_ID_SFP = 0x03, 235 SFP_PHYS_ID_SFP = 0x03,
235 SFP_PHYS_EXT_ID_SFP = 0x04, 236 SFP_PHYS_EXT_ID_SFP = 0x04,
236 SFP_CONNECTOR_UNSPEC = 0x00, 237 SFP_CONNECTOR_UNSPEC = 0x00,