0001
0002
0003
0004
0005
0006
0007
0008 #include "ksz8.h"
0009 #include "ksz_common.h"
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #define SMI_KSZ88XX_READ_PHY BIT(4)
0021
0022 static int ksz8863_mdio_read(void *ctx, const void *reg_buf, size_t reg_len,
0023 void *val_buf, size_t val_len)
0024 {
0025 struct ksz_device *dev = ctx;
0026 struct mdio_device *mdev;
0027 u8 reg = *(u8 *)reg_buf;
0028 u8 *val = val_buf;
0029 int i, ret = 0;
0030
0031 mdev = dev->priv;
0032
0033 mutex_lock_nested(&mdev->bus->mdio_lock, MDIO_MUTEX_NESTED);
0034 for (i = 0; i < val_len; i++) {
0035 int tmp = reg + i;
0036
0037 ret = __mdiobus_read(mdev->bus, ((tmp & 0xE0) >> 5) |
0038 SMI_KSZ88XX_READ_PHY, tmp);
0039 if (ret < 0)
0040 goto out;
0041
0042 val[i] = ret;
0043 }
0044 ret = 0;
0045
0046 out:
0047 mutex_unlock(&mdev->bus->mdio_lock);
0048
0049 return ret;
0050 }
0051
0052 static int ksz8863_mdio_write(void *ctx, const void *data, size_t count)
0053 {
0054 struct ksz_device *dev = ctx;
0055 struct mdio_device *mdev;
0056 int i, ret = 0;
0057 u32 reg;
0058 u8 *val;
0059
0060 mdev = dev->priv;
0061
0062 val = (u8 *)(data + 4);
0063 reg = *(u32 *)data;
0064
0065 mutex_lock_nested(&mdev->bus->mdio_lock, MDIO_MUTEX_NESTED);
0066 for (i = 0; i < (count - 4); i++) {
0067 int tmp = reg + i;
0068
0069 ret = __mdiobus_write(mdev->bus, ((tmp & 0xE0) >> 5),
0070 tmp, val[i]);
0071 if (ret < 0)
0072 goto out;
0073 }
0074
0075 out:
0076 mutex_unlock(&mdev->bus->mdio_lock);
0077
0078 return ret;
0079 }
0080
0081 static const struct regmap_bus regmap_smi[] = {
0082 {
0083 .read = ksz8863_mdio_read,
0084 .write = ksz8863_mdio_write,
0085 .max_raw_read = 1,
0086 .max_raw_write = 1,
0087 },
0088 {
0089 .read = ksz8863_mdio_read,
0090 .write = ksz8863_mdio_write,
0091 .val_format_endian_default = REGMAP_ENDIAN_BIG,
0092 .max_raw_read = 2,
0093 .max_raw_write = 2,
0094 },
0095 {
0096 .read = ksz8863_mdio_read,
0097 .write = ksz8863_mdio_write,
0098 .val_format_endian_default = REGMAP_ENDIAN_BIG,
0099 .max_raw_read = 4,
0100 .max_raw_write = 4,
0101 }
0102 };
0103
0104 static const struct regmap_config ksz8863_regmap_config[] = {
0105 {
0106 .name = "#8",
0107 .reg_bits = 8,
0108 .pad_bits = 24,
0109 .val_bits = 8,
0110 .cache_type = REGCACHE_NONE,
0111 .use_single_read = 1,
0112 .lock = ksz_regmap_lock,
0113 .unlock = ksz_regmap_unlock,
0114 },
0115 {
0116 .name = "#16",
0117 .reg_bits = 8,
0118 .pad_bits = 24,
0119 .val_bits = 16,
0120 .cache_type = REGCACHE_NONE,
0121 .use_single_read = 1,
0122 .lock = ksz_regmap_lock,
0123 .unlock = ksz_regmap_unlock,
0124 },
0125 {
0126 .name = "#32",
0127 .reg_bits = 8,
0128 .pad_bits = 24,
0129 .val_bits = 32,
0130 .cache_type = REGCACHE_NONE,
0131 .use_single_read = 1,
0132 .lock = ksz_regmap_lock,
0133 .unlock = ksz_regmap_unlock,
0134 }
0135 };
0136
0137 static int ksz8863_smi_probe(struct mdio_device *mdiodev)
0138 {
0139 struct regmap_config rc;
0140 struct ksz_device *dev;
0141 int ret;
0142 int i;
0143
0144 dev = ksz_switch_alloc(&mdiodev->dev, mdiodev);
0145 if (!dev)
0146 return -ENOMEM;
0147
0148 for (i = 0; i < ARRAY_SIZE(ksz8863_regmap_config); i++) {
0149 rc = ksz8863_regmap_config[i];
0150 rc.lock_arg = &dev->regmap_mutex;
0151 dev->regmap[i] = devm_regmap_init(&mdiodev->dev,
0152 ®map_smi[i], dev,
0153 &rc);
0154 if (IS_ERR(dev->regmap[i])) {
0155 ret = PTR_ERR(dev->regmap[i]);
0156 dev_err(&mdiodev->dev,
0157 "Failed to initialize regmap%i: %d\n",
0158 ksz8863_regmap_config[i].val_bits, ret);
0159 return ret;
0160 }
0161 }
0162
0163 if (mdiodev->dev.platform_data)
0164 dev->pdata = mdiodev->dev.platform_data;
0165
0166 ret = ksz_switch_register(dev);
0167
0168
0169 if (ret)
0170 return ret;
0171
0172 dev_set_drvdata(&mdiodev->dev, dev);
0173
0174 return 0;
0175 }
0176
0177 static void ksz8863_smi_remove(struct mdio_device *mdiodev)
0178 {
0179 struct ksz_device *dev = dev_get_drvdata(&mdiodev->dev);
0180
0181 if (dev)
0182 ksz_switch_remove(dev);
0183
0184 dev_set_drvdata(&mdiodev->dev, NULL);
0185 }
0186
0187 static void ksz8863_smi_shutdown(struct mdio_device *mdiodev)
0188 {
0189 struct ksz_device *dev = dev_get_drvdata(&mdiodev->dev);
0190
0191 if (dev)
0192 dsa_switch_shutdown(dev->ds);
0193
0194 dev_set_drvdata(&mdiodev->dev, NULL);
0195 }
0196
0197 static const struct of_device_id ksz8863_dt_ids[] = {
0198 {
0199 .compatible = "microchip,ksz8863",
0200 .data = &ksz_switch_chips[KSZ8830]
0201 },
0202 {
0203 .compatible = "microchip,ksz8873",
0204 .data = &ksz_switch_chips[KSZ8830]
0205 },
0206 { },
0207 };
0208 MODULE_DEVICE_TABLE(of, ksz8863_dt_ids);
0209
0210 static struct mdio_driver ksz8863_driver = {
0211 .probe = ksz8863_smi_probe,
0212 .remove = ksz8863_smi_remove,
0213 .shutdown = ksz8863_smi_shutdown,
0214 .mdiodrv.driver = {
0215 .name = "ksz8863-switch",
0216 .of_match_table = ksz8863_dt_ids,
0217 },
0218 };
0219
0220 mdio_module_driver(ksz8863_driver);
0221
0222 MODULE_AUTHOR("Michael Grzeschik <m.grzeschik@pengutronix.de>");
0223 MODULE_DESCRIPTION("Microchip KSZ8863 SMI Switch driver");
0224 MODULE_LICENSE("GPL v2");