0001
0002
0003
0004
0005
0006
0007 #include <linux/bitfield.h>
0008 #include <linux/bits.h>
0009 #include <linux/mdio.h>
0010 #include <linux/module.h>
0011 #include <linux/phy.h>
0012 #include <linux/if_vlan.h>
0013 #include <linux/of.h>
0014 #include "xrs700x.h"
0015 #include "xrs700x_reg.h"
0016
0017 #define XRS_MDIO_IBA0 0x10
0018 #define XRS_MDIO_IBA1 0x11
0019 #define XRS_MDIO_IBD 0x14
0020
0021 #define XRS_IB_READ 0x0
0022 #define XRS_IB_WRITE 0x1
0023
0024 static int xrs700x_mdio_reg_read(void *context, unsigned int reg,
0025 unsigned int *val)
0026 {
0027 struct mdio_device *mdiodev = context;
0028 struct device *dev = &mdiodev->dev;
0029 u16 uval;
0030 int ret;
0031
0032 uval = (u16)FIELD_GET(GENMASK(31, 16), reg);
0033
0034 ret = mdiodev_write(mdiodev, XRS_MDIO_IBA1, uval);
0035 if (ret < 0) {
0036 dev_err(dev, "xrs mdiobus_write returned %d\n", ret);
0037 return ret;
0038 }
0039
0040 uval = (u16)((reg & GENMASK(15, 1)) | XRS_IB_READ);
0041
0042 ret = mdiodev_write(mdiodev, XRS_MDIO_IBA0, uval);
0043 if (ret < 0) {
0044 dev_err(dev, "xrs mdiobus_write returned %d\n", ret);
0045 return ret;
0046 }
0047
0048 ret = mdiodev_read(mdiodev, XRS_MDIO_IBD);
0049 if (ret < 0) {
0050 dev_err(dev, "xrs mdiobus_read returned %d\n", ret);
0051 return ret;
0052 }
0053
0054 *val = (unsigned int)ret;
0055
0056 return 0;
0057 }
0058
0059 static int xrs700x_mdio_reg_write(void *context, unsigned int reg,
0060 unsigned int val)
0061 {
0062 struct mdio_device *mdiodev = context;
0063 struct device *dev = &mdiodev->dev;
0064 u16 uval;
0065 int ret;
0066
0067 ret = mdiodev_write(mdiodev, XRS_MDIO_IBD, (u16)val);
0068 if (ret < 0) {
0069 dev_err(dev, "xrs mdiobus_write returned %d\n", ret);
0070 return ret;
0071 }
0072
0073 uval = (u16)FIELD_GET(GENMASK(31, 16), reg);
0074
0075 ret = mdiodev_write(mdiodev, XRS_MDIO_IBA1, uval);
0076 if (ret < 0) {
0077 dev_err(dev, "xrs mdiobus_write returned %d\n", ret);
0078 return ret;
0079 }
0080
0081 uval = (u16)((reg & GENMASK(15, 1)) | XRS_IB_WRITE);
0082
0083 ret = mdiodev_write(mdiodev, XRS_MDIO_IBA0, uval);
0084 if (ret < 0) {
0085 dev_err(dev, "xrs mdiobus_write returned %d\n", ret);
0086 return ret;
0087 }
0088
0089 return 0;
0090 }
0091
0092 static const struct regmap_config xrs700x_mdio_regmap_config = {
0093 .val_bits = 16,
0094 .reg_stride = 2,
0095 .reg_bits = 32,
0096 .pad_bits = 0,
0097 .write_flag_mask = 0,
0098 .read_flag_mask = 0,
0099 .reg_read = xrs700x_mdio_reg_read,
0100 .reg_write = xrs700x_mdio_reg_write,
0101 .max_register = XRS_VLAN(VLAN_N_VID - 1),
0102 .cache_type = REGCACHE_NONE,
0103 .reg_format_endian = REGMAP_ENDIAN_BIG,
0104 .val_format_endian = REGMAP_ENDIAN_BIG
0105 };
0106
0107 static int xrs700x_mdio_probe(struct mdio_device *mdiodev)
0108 {
0109 struct xrs700x *priv;
0110 int ret;
0111
0112 priv = xrs700x_switch_alloc(&mdiodev->dev, mdiodev);
0113 if (!priv)
0114 return -ENOMEM;
0115
0116 priv->regmap = devm_regmap_init(&mdiodev->dev, NULL, mdiodev,
0117 &xrs700x_mdio_regmap_config);
0118 if (IS_ERR(priv->regmap)) {
0119 ret = PTR_ERR(priv->regmap);
0120 dev_err(&mdiodev->dev, "Failed to initialize regmap: %d\n", ret);
0121 return ret;
0122 }
0123
0124 dev_set_drvdata(&mdiodev->dev, priv);
0125
0126 ret = xrs700x_switch_register(priv);
0127
0128
0129 if (ret)
0130 return ret;
0131
0132 return 0;
0133 }
0134
0135 static void xrs700x_mdio_remove(struct mdio_device *mdiodev)
0136 {
0137 struct xrs700x *priv = dev_get_drvdata(&mdiodev->dev);
0138
0139 if (!priv)
0140 return;
0141
0142 xrs700x_switch_remove(priv);
0143
0144 dev_set_drvdata(&mdiodev->dev, NULL);
0145 }
0146
0147 static void xrs700x_mdio_shutdown(struct mdio_device *mdiodev)
0148 {
0149 struct xrs700x *priv = dev_get_drvdata(&mdiodev->dev);
0150
0151 if (!priv)
0152 return;
0153
0154 xrs700x_switch_shutdown(priv);
0155
0156 dev_set_drvdata(&mdiodev->dev, NULL);
0157 }
0158
0159 static const struct of_device_id __maybe_unused xrs700x_mdio_dt_ids[] = {
0160 { .compatible = "arrow,xrs7003e", .data = &xrs7003e_info },
0161 { .compatible = "arrow,xrs7003f", .data = &xrs7003f_info },
0162 { .compatible = "arrow,xrs7004e", .data = &xrs7004e_info },
0163 { .compatible = "arrow,xrs7004f", .data = &xrs7004f_info },
0164 {},
0165 };
0166 MODULE_DEVICE_TABLE(of, xrs700x_mdio_dt_ids);
0167
0168 static struct mdio_driver xrs700x_mdio_driver = {
0169 .mdiodrv.driver = {
0170 .name = "xrs700x-mdio",
0171 .of_match_table = of_match_ptr(xrs700x_mdio_dt_ids),
0172 },
0173 .probe = xrs700x_mdio_probe,
0174 .remove = xrs700x_mdio_remove,
0175 .shutdown = xrs700x_mdio_shutdown,
0176 };
0177
0178 mdio_module_driver(xrs700x_mdio_driver);
0179
0180 MODULE_AUTHOR("George McCollister <george.mccollister@gmail.com>");
0181 MODULE_DESCRIPTION("Arrow SpeedChips XRS700x DSA MDIO driver");
0182 MODULE_LICENSE("GPL v2");