This source file includes following definitions.
- fsl_pq_mdio_write
- fsl_pq_mdio_read
- fsl_pq_mdio_reset
- get_gfar_tbipa_from_mdio
- get_gfar_tbipa_from_mii
- get_etsec_tbipa
- get_ucc_tbipa
- ucc_configure
- set_tbipa
- fsl_pq_mdio_probe
- fsl_pq_mdio_remove
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 #include <linux/kernel.h>
  15 #include <linux/string.h>
  16 #include <linux/errno.h>
  17 #include <linux/slab.h>
  18 #include <linux/delay.h>
  19 #include <linux/module.h>
  20 #include <linux/mii.h>
  21 #include <linux/of_address.h>
  22 #include <linux/of_mdio.h>
  23 #include <linux/of_device.h>
  24 
  25 #include <asm/io.h>
  26 #if IS_ENABLED(CONFIG_UCC_GETH)
  27 #include <soc/fsl/qe/ucc.h>
  28 #endif
  29 
  30 #include "gianfar.h"
  31 
  32 #define MIIMIND_BUSY            0x00000001
  33 #define MIIMIND_NOTVALID        0x00000004
  34 #define MIIMCFG_INIT_VALUE      0x00000007
  35 #define MIIMCFG_RESET           0x80000000
  36 
  37 #define MII_READ_COMMAND        0x00000001
  38 
  39 struct fsl_pq_mii {
  40         u32 miimcfg;    
  41         u32 miimcom;    
  42         u32 miimadd;    
  43         u32 miimcon;    
  44         u32 miimstat;   
  45         u32 miimind;    
  46 };
  47 
  48 struct fsl_pq_mdio {
  49         u8 res1[16];
  50         u32 ieventm;    
  51         u32 imaskm;     
  52         u8 res2[4];
  53         u32 emapm;      
  54         u8 res3[1280];
  55         struct fsl_pq_mii mii;
  56         u8 res4[28];
  57         u32 utbipar;    
  58         u8 res5[2728];
  59 } __packed;
  60 
  61 
  62 #define MII_TIMEOUT     1000
  63 
  64 struct fsl_pq_mdio_priv {
  65         void __iomem *map;
  66         struct fsl_pq_mii __iomem *regs;
  67 };
  68 
  69 
  70 
  71 
  72 
  73 
  74 
  75 
  76 
  77 
  78 
  79 
  80 
  81 struct fsl_pq_mdio_data {
  82         unsigned int mii_offset;        
  83         uint32_t __iomem * (*get_tbipa)(void __iomem *p);
  84         void (*ucc_configure)(phys_addr_t start, phys_addr_t end);
  85 };
  86 
  87 
  88 
  89 
  90 
  91 
  92 
  93 
  94 
  95 
  96 static int fsl_pq_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
  97                 u16 value)
  98 {
  99         struct fsl_pq_mdio_priv *priv = bus->priv;
 100         struct fsl_pq_mii __iomem *regs = priv->regs;
 101         unsigned int timeout;
 102 
 103         
 104         iowrite32be((mii_id << 8) | regnum, ®s->miimadd);
 105 
 106         
 107         iowrite32be(value, ®s->miimcon);
 108 
 109         
 110         timeout = MII_TIMEOUT;
 111         while ((ioread32be(®s->miimind) & MIIMIND_BUSY) && timeout) {
 112                 cpu_relax();
 113                 timeout--;
 114         }
 115 
 116         return timeout ? 0 : -ETIMEDOUT;
 117 }
 118 
 119 
 120 
 121 
 122 
 123 
 124 
 125 
 126 
 127 
 128 
 129 static int fsl_pq_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
 130 {
 131         struct fsl_pq_mdio_priv *priv = bus->priv;
 132         struct fsl_pq_mii __iomem *regs = priv->regs;
 133         unsigned int timeout;
 134         u16 value;
 135 
 136         
 137         iowrite32be((mii_id << 8) | regnum, ®s->miimadd);
 138 
 139         
 140         iowrite32be(0, ®s->miimcom);
 141         iowrite32be(MII_READ_COMMAND, ®s->miimcom);
 142 
 143         
 144         timeout = MII_TIMEOUT;
 145         while ((ioread32be(®s->miimind) &
 146                (MIIMIND_NOTVALID | MIIMIND_BUSY)) && timeout) {
 147                 cpu_relax();
 148                 timeout--;
 149         }
 150 
 151         if (!timeout)
 152                 return -ETIMEDOUT;
 153 
 154         
 155         value = ioread32be(®s->miimstat);
 156 
 157         dev_dbg(&bus->dev, "read %04x from address %x/%x\n", value, mii_id, regnum);
 158         return value;
 159 }
 160 
 161 
 162 static int fsl_pq_mdio_reset(struct mii_bus *bus)
 163 {
 164         struct fsl_pq_mdio_priv *priv = bus->priv;
 165         struct fsl_pq_mii __iomem *regs = priv->regs;
 166         unsigned int timeout;
 167 
 168         mutex_lock(&bus->mdio_lock);
 169 
 170         
 171         iowrite32be(MIIMCFG_RESET, ®s->miimcfg);
 172 
 173         
 174         iowrite32be(MIIMCFG_INIT_VALUE, ®s->miimcfg);
 175 
 176         
 177         timeout = MII_TIMEOUT;
 178         while ((ioread32be(®s->miimind) & MIIMIND_BUSY) && timeout) {
 179                 cpu_relax();
 180                 timeout--;
 181         }
 182 
 183         mutex_unlock(&bus->mdio_lock);
 184 
 185         if (!timeout) {
 186                 dev_err(&bus->dev, "timeout waiting for MII bus\n");
 187                 return -EBUSY;
 188         }
 189 
 190         return 0;
 191 }
 192 
 193 #if IS_ENABLED(CONFIG_GIANFAR)
 194 
 195 
 196 
 197 
 198 
 199 
 200 
 201 static uint32_t __iomem *get_gfar_tbipa_from_mdio(void __iomem *p)
 202 {
 203         struct gfar __iomem *enet_regs = p;
 204 
 205         return &enet_regs->tbipa;
 206 }
 207 
 208 
 209 
 210 
 211 
 212 static uint32_t __iomem *get_gfar_tbipa_from_mii(void __iomem *p)
 213 {
 214         return get_gfar_tbipa_from_mdio(container_of(p, struct gfar, gfar_mii_regs));
 215 }
 216 
 217 
 218 
 219 
 220 static uint32_t __iomem *get_etsec_tbipa(void __iomem *p)
 221 {
 222         return p;
 223 }
 224 #endif
 225 
 226 #if IS_ENABLED(CONFIG_UCC_GETH)
 227 
 228 
 229 
 230 
 231 static uint32_t __iomem *get_ucc_tbipa(void __iomem *p)
 232 {
 233         struct fsl_pq_mdio __iomem *mdio = container_of(p, struct fsl_pq_mdio, mii);
 234 
 235         return &mdio->utbipar;
 236 }
 237 
 238 
 239 
 240 
 241 
 242 
 243 
 244 
 245 
 246 
 247 
 248 
 249 static void ucc_configure(phys_addr_t start, phys_addr_t end)
 250 {
 251         static bool found_mii_master;
 252         struct device_node *np = NULL;
 253 
 254         if (found_mii_master)
 255                 return;
 256 
 257         for_each_compatible_node(np, NULL, "ucc_geth") {
 258                 struct resource res;
 259                 const uint32_t *iprop;
 260                 uint32_t id;
 261                 int ret;
 262 
 263                 ret = of_address_to_resource(np, 0, &res);
 264                 if (ret < 0) {
 265                         pr_debug("fsl-pq-mdio: no address range in node %pOF\n",
 266                                  np);
 267                         continue;
 268                 }
 269 
 270                 
 271                 if ((start < res.start) || (end > res.end))
 272                         continue;
 273 
 274                 iprop = of_get_property(np, "cell-index", NULL);
 275                 if (!iprop) {
 276                         iprop = of_get_property(np, "device-id", NULL);
 277                         if (!iprop) {
 278                                 pr_debug("fsl-pq-mdio: no UCC ID in node %pOF\n",
 279                                          np);
 280                                 continue;
 281                         }
 282                 }
 283 
 284                 id = be32_to_cpup(iprop);
 285 
 286                 
 287 
 288 
 289 
 290                 if (ucc_set_qe_mux_mii_mng(id - 1) < 0) {
 291                         pr_debug("fsl-pq-mdio: invalid UCC ID in node %pOF\n",
 292                                  np);
 293                         continue;
 294                 }
 295 
 296                 pr_debug("fsl-pq-mdio: setting node UCC%u to MII master\n", id);
 297                 found_mii_master = true;
 298         }
 299 }
 300 
 301 #endif
 302 
 303 static const struct of_device_id fsl_pq_mdio_match[] = {
 304 #if IS_ENABLED(CONFIG_GIANFAR)
 305         {
 306                 .compatible = "fsl,gianfar-tbi",
 307                 .data = &(struct fsl_pq_mdio_data) {
 308                         .mii_offset = 0,
 309                         .get_tbipa = get_gfar_tbipa_from_mii,
 310                 },
 311         },
 312         {
 313                 .compatible = "fsl,gianfar-mdio",
 314                 .data = &(struct fsl_pq_mdio_data) {
 315                         .mii_offset = 0,
 316                         .get_tbipa = get_gfar_tbipa_from_mii,
 317                 },
 318         },
 319         {
 320                 .type = "mdio",
 321                 .compatible = "gianfar",
 322                 .data = &(struct fsl_pq_mdio_data) {
 323                         .mii_offset = offsetof(struct fsl_pq_mdio, mii),
 324                         .get_tbipa = get_gfar_tbipa_from_mdio,
 325                 },
 326         },
 327         {
 328                 .compatible = "fsl,etsec2-tbi",
 329                 .data = &(struct fsl_pq_mdio_data) {
 330                         .mii_offset = offsetof(struct fsl_pq_mdio, mii),
 331                         .get_tbipa = get_etsec_tbipa,
 332                 },
 333         },
 334         {
 335                 .compatible = "fsl,etsec2-mdio",
 336                 .data = &(struct fsl_pq_mdio_data) {
 337                         .mii_offset = offsetof(struct fsl_pq_mdio, mii),
 338                         .get_tbipa = get_etsec_tbipa,
 339                 },
 340         },
 341 #endif
 342 #if IS_ENABLED(CONFIG_UCC_GETH)
 343         {
 344                 .compatible = "fsl,ucc-mdio",
 345                 .data = &(struct fsl_pq_mdio_data) {
 346                         .mii_offset = 0,
 347                         .get_tbipa = get_ucc_tbipa,
 348                         .ucc_configure = ucc_configure,
 349                 },
 350         },
 351         {
 352                 
 353                 .type = "mdio",
 354                 .compatible = "ucc_geth_phy",
 355                 .data = &(struct fsl_pq_mdio_data) {
 356                         .mii_offset = 0,
 357                         .get_tbipa = get_ucc_tbipa,
 358                         .ucc_configure = ucc_configure,
 359                 },
 360         },
 361 #endif
 362         
 363         {
 364                 .compatible = "fsl,fman-mdio",
 365                 .data = &(struct fsl_pq_mdio_data) {
 366                         .mii_offset = 0,
 367                         
 368                 },
 369         },
 370 
 371         {},
 372 };
 373 MODULE_DEVICE_TABLE(of, fsl_pq_mdio_match);
 374 
 375 static void set_tbipa(const u32 tbipa_val, struct platform_device *pdev,
 376                       uint32_t __iomem * (*get_tbipa)(void __iomem *),
 377                       void __iomem *reg_map, struct resource *reg_res)
 378 {
 379         struct device_node *np = pdev->dev.of_node;
 380         uint32_t __iomem *tbipa;
 381         bool tbipa_mapped;
 382 
 383         tbipa = of_iomap(np, 1);
 384         if (tbipa) {
 385                 tbipa_mapped = true;
 386         } else {
 387                 tbipa_mapped = false;
 388                 tbipa = (*get_tbipa)(reg_map);
 389 
 390                 
 391 
 392 
 393 
 394 
 395 
 396                 if ((void *)tbipa > reg_map + resource_size(reg_res) - 4)
 397                         dev_err(&pdev->dev, "invalid register map (should be at least 0x%04zx to contain TBI address)\n",
 398                                 ((void *)tbipa - reg_map) + 4);
 399         }
 400 
 401         iowrite32be(be32_to_cpu(tbipa_val), tbipa);
 402 
 403         if (tbipa_mapped)
 404                 iounmap(tbipa);
 405 }
 406 
 407 static int fsl_pq_mdio_probe(struct platform_device *pdev)
 408 {
 409         const struct of_device_id *id =
 410                 of_match_device(fsl_pq_mdio_match, &pdev->dev);
 411         const struct fsl_pq_mdio_data *data;
 412         struct device_node *np = pdev->dev.of_node;
 413         struct resource res;
 414         struct device_node *tbi;
 415         struct fsl_pq_mdio_priv *priv;
 416         struct mii_bus *new_bus;
 417         int err;
 418 
 419         if (!id) {
 420                 dev_err(&pdev->dev, "Failed to match device\n");
 421                 return -ENODEV;
 422         }
 423 
 424         data = id->data;
 425 
 426         dev_dbg(&pdev->dev, "found %s compatible node\n", id->compatible);
 427 
 428         new_bus = mdiobus_alloc_size(sizeof(*priv));
 429         if (!new_bus)
 430                 return -ENOMEM;
 431 
 432         priv = new_bus->priv;
 433         new_bus->name = "Freescale PowerQUICC MII Bus",
 434         new_bus->read = &fsl_pq_mdio_read;
 435         new_bus->write = &fsl_pq_mdio_write;
 436         new_bus->reset = &fsl_pq_mdio_reset;
 437 
 438         err = of_address_to_resource(np, 0, &res);
 439         if (err < 0) {
 440                 dev_err(&pdev->dev, "could not obtain address information\n");
 441                 goto error;
 442         }
 443 
 444         snprintf(new_bus->id, MII_BUS_ID_SIZE, "%pOFn@%llx", np,
 445                  (unsigned long long)res.start);
 446 
 447         priv->map = of_iomap(np, 0);
 448         if (!priv->map) {
 449                 err = -ENOMEM;
 450                 goto error;
 451         }
 452 
 453         
 454 
 455 
 456 
 457 
 458 
 459         if (data->mii_offset > resource_size(&res)) {
 460                 dev_err(&pdev->dev, "invalid register map\n");
 461                 err = -EINVAL;
 462                 goto error;
 463         }
 464         priv->regs = priv->map + data->mii_offset;
 465 
 466         new_bus->parent = &pdev->dev;
 467         platform_set_drvdata(pdev, new_bus);
 468 
 469         if (data->get_tbipa) {
 470                 for_each_child_of_node(np, tbi) {
 471                         if (of_node_is_type(tbi, "tbi-phy")) {
 472                                 dev_dbg(&pdev->dev, "found TBI PHY node %pOFP\n",
 473                                         tbi);
 474                                 break;
 475                         }
 476                 }
 477 
 478                 if (tbi) {
 479                         const u32 *prop = of_get_property(tbi, "reg", NULL);
 480                         if (!prop) {
 481                                 dev_err(&pdev->dev,
 482                                         "missing 'reg' property in node %pOF\n",
 483                                         tbi);
 484                                 err = -EBUSY;
 485                                 goto error;
 486                         }
 487                         set_tbipa(*prop, pdev,
 488                                   data->get_tbipa, priv->map, &res);
 489                 }
 490         }
 491 
 492         if (data->ucc_configure)
 493                 data->ucc_configure(res.start, res.end);
 494 
 495         err = of_mdiobus_register(new_bus, np);
 496         if (err) {
 497                 dev_err(&pdev->dev, "cannot register %s as MDIO bus\n",
 498                         new_bus->name);
 499                 goto error;
 500         }
 501 
 502         return 0;
 503 
 504 error:
 505         if (priv->map)
 506                 iounmap(priv->map);
 507 
 508         kfree(new_bus);
 509 
 510         return err;
 511 }
 512 
 513 
 514 static int fsl_pq_mdio_remove(struct platform_device *pdev)
 515 {
 516         struct device *device = &pdev->dev;
 517         struct mii_bus *bus = dev_get_drvdata(device);
 518         struct fsl_pq_mdio_priv *priv = bus->priv;
 519 
 520         mdiobus_unregister(bus);
 521 
 522         iounmap(priv->map);
 523         mdiobus_free(bus);
 524 
 525         return 0;
 526 }
 527 
 528 static struct platform_driver fsl_pq_mdio_driver = {
 529         .driver = {
 530                 .name = "fsl-pq_mdio",
 531                 .of_match_table = fsl_pq_mdio_match,
 532         },
 533         .probe = fsl_pq_mdio_probe,
 534         .remove = fsl_pq_mdio_remove,
 535 };
 536 
 537 module_platform_driver(fsl_pq_mdio_driver);
 538 
 539 MODULE_LICENSE("GPL");