0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/kernel.h>
0015 #include <linux/string.h>
0016 #include <linux/errno.h>
0017 #include <linux/slab.h>
0018 #include <linux/delay.h>
0019 #include <linux/module.h>
0020 #include <linux/mii.h>
0021 #include <linux/of_address.h>
0022 #include <linux/of_mdio.h>
0023 #include <linux/of_device.h>
0024
0025 #include <asm/io.h>
0026 #if IS_ENABLED(CONFIG_UCC_GETH)
0027 #include <soc/fsl/qe/ucc.h>
0028 #endif
0029
0030 #include "gianfar.h"
0031
0032 #define MIIMIND_BUSY 0x00000001
0033 #define MIIMIND_NOTVALID 0x00000004
0034 #define MIIMCFG_INIT_VALUE 0x00000007
0035 #define MIIMCFG_RESET 0x80000000
0036
0037 #define MII_READ_COMMAND 0x00000001
0038
0039 struct fsl_pq_mii {
0040 u32 miimcfg;
0041 u32 miimcom;
0042 u32 miimadd;
0043 u32 miimcon;
0044 u32 miimstat;
0045 u32 miimind;
0046 };
0047
0048 struct fsl_pq_mdio {
0049 u8 res1[16];
0050 u32 ieventm;
0051 u32 imaskm;
0052 u8 res2[4];
0053 u32 emapm;
0054 u8 res3[1280];
0055 struct fsl_pq_mii mii;
0056 u8 res4[28];
0057 u32 utbipar;
0058 u8 res5[2728];
0059 } __packed;
0060
0061
0062 #define MII_TIMEOUT 1000
0063
0064 struct fsl_pq_mdio_priv {
0065 void __iomem *map;
0066 struct fsl_pq_mii __iomem *regs;
0067 };
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081 struct fsl_pq_mdio_data {
0082 unsigned int mii_offset;
0083 uint32_t __iomem * (*get_tbipa)(void __iomem *p);
0084 void (*ucc_configure)(phys_addr_t start, phys_addr_t end);
0085 };
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096 static int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
0097 u16 value)
0098 {
0099 struct fsl_pq_mdio_priv *priv = bus->priv;
0100 struct fsl_pq_mii __iomem *regs = priv->regs;
0101 unsigned int timeout;
0102
0103
0104 iowrite32be((mii_id << 8) | regnum, ®s->miimadd);
0105
0106
0107 iowrite32be(value, ®s->miimcon);
0108
0109
0110 timeout = MII_TIMEOUT;
0111 while ((ioread32be(®s->miimind) & MIIMIND_BUSY) && timeout) {
0112 cpu_relax();
0113 timeout--;
0114 }
0115
0116 return timeout ? 0 : -ETIMEDOUT;
0117 }
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129 static int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
0130 {
0131 struct fsl_pq_mdio_priv *priv = bus->priv;
0132 struct fsl_pq_mii __iomem *regs = priv->regs;
0133 unsigned int timeout;
0134 u16 value;
0135
0136
0137 iowrite32be((mii_id << 8) | regnum, ®s->miimadd);
0138
0139
0140 iowrite32be(0, ®s->miimcom);
0141 iowrite32be(MII_READ_COMMAND, ®s->miimcom);
0142
0143
0144 timeout = MII_TIMEOUT;
0145 while ((ioread32be(®s->miimind) &
0146 (MIIMIND_NOTVALID | MIIMIND_BUSY)) && timeout) {
0147 cpu_relax();
0148 timeout--;
0149 }
0150
0151 if (!timeout)
0152 return -ETIMEDOUT;
0153
0154
0155 value = ioread32be(®s->miimstat);
0156
0157 dev_dbg(&bus->dev, "read %04x from address %x/%x\n", value, mii_id, regnum);
0158 return value;
0159 }
0160
0161
0162 static int fsl_pq_mdio_reset(struct mii_bus *bus)
0163 {
0164 struct fsl_pq_mdio_priv *priv = bus->priv;
0165 struct fsl_pq_mii __iomem *regs = priv->regs;
0166 unsigned int timeout;
0167
0168 mutex_lock(&bus->mdio_lock);
0169
0170
0171 iowrite32be(MIIMCFG_RESET, ®s->miimcfg);
0172
0173
0174 iowrite32be(MIIMCFG_INIT_VALUE, ®s->miimcfg);
0175
0176
0177 timeout = MII_TIMEOUT;
0178 while ((ioread32be(®s->miimind) & MIIMIND_BUSY) && timeout) {
0179 cpu_relax();
0180 timeout--;
0181 }
0182
0183 mutex_unlock(&bus->mdio_lock);
0184
0185 if (!timeout) {
0186 dev_err(&bus->dev, "timeout waiting for MII bus\n");
0187 return -EBUSY;
0188 }
0189
0190 return 0;
0191 }
0192
0193 #if IS_ENABLED(CONFIG_GIANFAR)
0194
0195
0196
0197
0198
0199
0200
0201 static uint32_t __iomem *get_gfar_tbipa_from_mdio(void __iomem *p)
0202 {
0203 struct gfar __iomem *enet_regs = p;
0204
0205 return &enet_regs->tbipa;
0206 }
0207
0208
0209
0210
0211
0212 static uint32_t __iomem *get_gfar_tbipa_from_mii(void __iomem *p)
0213 {
0214 return get_gfar_tbipa_from_mdio(container_of(p, struct gfar, gfar_mii_regs));
0215 }
0216
0217
0218
0219
0220 static uint32_t __iomem *get_etsec_tbipa(void __iomem *p)
0221 {
0222 return p;
0223 }
0224 #endif
0225
0226 #if IS_ENABLED(CONFIG_UCC_GETH)
0227
0228
0229
0230
0231 static uint32_t __iomem *get_ucc_tbipa(void __iomem *p)
0232 {
0233 struct fsl_pq_mdio __iomem *mdio = container_of(p, struct fsl_pq_mdio, mii);
0234
0235 return &mdio->utbipar;
0236 }
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249 static void ucc_configure(phys_addr_t start, phys_addr_t end)
0250 {
0251 static bool found_mii_master;
0252 struct device_node *np = NULL;
0253
0254 if (found_mii_master)
0255 return;
0256
0257 for_each_compatible_node(np, NULL, "ucc_geth") {
0258 struct resource res;
0259 const uint32_t *iprop;
0260 uint32_t id;
0261 int ret;
0262
0263 ret = of_address_to_resource(np, 0, &res);
0264 if (ret < 0) {
0265 pr_debug("fsl-pq-mdio: no address range in node %pOF\n",
0266 np);
0267 continue;
0268 }
0269
0270
0271 if ((start < res.start) || (end > res.end))
0272 continue;
0273
0274 iprop = of_get_property(np, "cell-index", NULL);
0275 if (!iprop) {
0276 iprop = of_get_property(np, "device-id", NULL);
0277 if (!iprop) {
0278 pr_debug("fsl-pq-mdio: no UCC ID in node %pOF\n",
0279 np);
0280 continue;
0281 }
0282 }
0283
0284 id = be32_to_cpup(iprop);
0285
0286
0287
0288
0289
0290 if (ucc_set_qe_mux_mii_mng(id - 1) < 0) {
0291 pr_debug("fsl-pq-mdio: invalid UCC ID in node %pOF\n",
0292 np);
0293 continue;
0294 }
0295
0296 pr_debug("fsl-pq-mdio: setting node UCC%u to MII master\n", id);
0297 found_mii_master = true;
0298 }
0299 }
0300
0301 #endif
0302
0303 static const struct of_device_id fsl_pq_mdio_match[] = {
0304 #if IS_ENABLED(CONFIG_GIANFAR)
0305 {
0306 .compatible = "fsl,gianfar-tbi",
0307 .data = &(struct fsl_pq_mdio_data) {
0308 .mii_offset = 0,
0309 .get_tbipa = get_gfar_tbipa_from_mii,
0310 },
0311 },
0312 {
0313 .compatible = "fsl,gianfar-mdio",
0314 .data = &(struct fsl_pq_mdio_data) {
0315 .mii_offset = 0,
0316 .get_tbipa = get_gfar_tbipa_from_mii,
0317 },
0318 },
0319 {
0320 .type = "mdio",
0321 .compatible = "gianfar",
0322 .data = &(struct fsl_pq_mdio_data) {
0323 .mii_offset = offsetof(struct fsl_pq_mdio, mii),
0324 .get_tbipa = get_gfar_tbipa_from_mdio,
0325 },
0326 },
0327 {
0328 .compatible = "fsl,etsec2-tbi",
0329 .data = &(struct fsl_pq_mdio_data) {
0330 .mii_offset = offsetof(struct fsl_pq_mdio, mii),
0331 .get_tbipa = get_etsec_tbipa,
0332 },
0333 },
0334 {
0335 .compatible = "fsl,etsec2-mdio",
0336 .data = &(struct fsl_pq_mdio_data) {
0337 .mii_offset = offsetof(struct fsl_pq_mdio, mii),
0338 .get_tbipa = get_etsec_tbipa,
0339 },
0340 },
0341 #endif
0342 #if IS_ENABLED(CONFIG_UCC_GETH)
0343 {
0344 .compatible = "fsl,ucc-mdio",
0345 .data = &(struct fsl_pq_mdio_data) {
0346 .mii_offset = 0,
0347 .get_tbipa = get_ucc_tbipa,
0348 .ucc_configure = ucc_configure,
0349 },
0350 },
0351 {
0352
0353 .type = "mdio",
0354 .compatible = "ucc_geth_phy",
0355 .data = &(struct fsl_pq_mdio_data) {
0356 .mii_offset = 0,
0357 .get_tbipa = get_ucc_tbipa,
0358 .ucc_configure = ucc_configure,
0359 },
0360 },
0361 #endif
0362
0363 {
0364 .compatible = "fsl,fman-mdio",
0365 .data = &(struct fsl_pq_mdio_data) {
0366 .mii_offset = 0,
0367
0368 },
0369 },
0370
0371 {},
0372 };
0373 MODULE_DEVICE_TABLE(of, fsl_pq_mdio_match);
0374
0375 static void set_tbipa(const u32 tbipa_val, struct platform_device *pdev,
0376 uint32_t __iomem * (*get_tbipa)(void __iomem *),
0377 void __iomem *reg_map, struct resource *reg_res)
0378 {
0379 struct device_node *np = pdev->dev.of_node;
0380 uint32_t __iomem *tbipa;
0381 bool tbipa_mapped;
0382
0383 tbipa = of_iomap(np, 1);
0384 if (tbipa) {
0385 tbipa_mapped = true;
0386 } else {
0387 tbipa_mapped = false;
0388 tbipa = (*get_tbipa)(reg_map);
0389
0390
0391
0392
0393
0394
0395
0396 if ((void *)tbipa > reg_map + resource_size(reg_res) - 4)
0397 dev_err(&pdev->dev, "invalid register map (should be at least 0x%04zx to contain TBI address)\n",
0398 ((void *)tbipa - reg_map) + 4);
0399 }
0400
0401 iowrite32be(be32_to_cpu(tbipa_val), tbipa);
0402
0403 if (tbipa_mapped)
0404 iounmap(tbipa);
0405 }
0406
0407 static int fsl_pq_mdio_probe(struct platform_device *pdev)
0408 {
0409 const struct of_device_id *id =
0410 of_match_device(fsl_pq_mdio_match, &pdev->dev);
0411 const struct fsl_pq_mdio_data *data;
0412 struct device_node *np = pdev->dev.of_node;
0413 struct resource res;
0414 struct device_node *tbi;
0415 struct fsl_pq_mdio_priv *priv;
0416 struct mii_bus *new_bus;
0417 int err;
0418
0419 if (!id) {
0420 dev_err(&pdev->dev, "Failed to match device\n");
0421 return -ENODEV;
0422 }
0423
0424 data = id->data;
0425
0426 dev_dbg(&pdev->dev, "found %s compatible node\n", id->compatible);
0427
0428 new_bus = mdiobus_alloc_size(sizeof(*priv));
0429 if (!new_bus)
0430 return -ENOMEM;
0431
0432 priv = new_bus->priv;
0433 new_bus->name = "Freescale PowerQUICC MII Bus";
0434 new_bus->read = &fsl_pq_mdio_read;
0435 new_bus->write = &fsl_pq_mdio_write;
0436 new_bus->reset = &fsl_pq_mdio_reset;
0437
0438 err = of_address_to_resource(np, 0, &res);
0439 if (err < 0) {
0440 dev_err(&pdev->dev, "could not obtain address information\n");
0441 goto error;
0442 }
0443
0444 snprintf(new_bus->id, MII_BUS_ID_SIZE, "%pOFn@%llx", np,
0445 (unsigned long long)res.start);
0446
0447 priv->map = of_iomap(np, 0);
0448 if (!priv->map) {
0449 err = -ENOMEM;
0450 goto error;
0451 }
0452
0453
0454
0455
0456
0457
0458
0459 if (data->mii_offset > resource_size(&res)) {
0460 dev_err(&pdev->dev, "invalid register map\n");
0461 err = -EINVAL;
0462 goto error;
0463 }
0464 priv->regs = priv->map + data->mii_offset;
0465
0466 new_bus->parent = &pdev->dev;
0467 platform_set_drvdata(pdev, new_bus);
0468
0469 if (data->get_tbipa) {
0470 for_each_child_of_node(np, tbi) {
0471 if (of_node_is_type(tbi, "tbi-phy")) {
0472 dev_dbg(&pdev->dev, "found TBI PHY node %pOFP\n",
0473 tbi);
0474 break;
0475 }
0476 }
0477
0478 if (tbi) {
0479 const u32 *prop = of_get_property(tbi, "reg", NULL);
0480 if (!prop) {
0481 dev_err(&pdev->dev,
0482 "missing 'reg' property in node %pOF\n",
0483 tbi);
0484 err = -EBUSY;
0485 goto error;
0486 }
0487 set_tbipa(*prop, pdev,
0488 data->get_tbipa, priv->map, &res);
0489 }
0490 }
0491
0492 if (data->ucc_configure)
0493 data->ucc_configure(res.start, res.end);
0494
0495 err = of_mdiobus_register(new_bus, np);
0496 if (err) {
0497 dev_err(&pdev->dev, "cannot register %s as MDIO bus\n",
0498 new_bus->name);
0499 goto error;
0500 }
0501
0502 return 0;
0503
0504 error:
0505 if (priv->map)
0506 iounmap(priv->map);
0507
0508 kfree(new_bus);
0509
0510 return err;
0511 }
0512
0513
0514 static int fsl_pq_mdio_remove(struct platform_device *pdev)
0515 {
0516 struct device *device = &pdev->dev;
0517 struct mii_bus *bus = dev_get_drvdata(device);
0518 struct fsl_pq_mdio_priv *priv = bus->priv;
0519
0520 mdiobus_unregister(bus);
0521
0522 iounmap(priv->map);
0523 mdiobus_free(bus);
0524
0525 return 0;
0526 }
0527
0528 static struct platform_driver fsl_pq_mdio_driver = {
0529 .driver = {
0530 .name = "fsl-pq_mdio",
0531 .of_match_table = fsl_pq_mdio_match,
0532 },
0533 .probe = fsl_pq_mdio_probe,
0534 .remove = fsl_pq_mdio_remove,
0535 };
0536
0537 module_platform_driver(fsl_pq_mdio_driver);
0538
0539 MODULE_LICENSE("GPL");