129-phy-add-I2C-mdio-bus.patch 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. From 7f36ac946bfbd4090b8b94be3661b41ac73e21f4 Mon Sep 17 00:00:00 2001
  2. From: Russell King <rmk+kernel@arm.linux.org.uk>
  3. Date: Fri, 25 Sep 2015 17:43:52 +0100
  4. Subject: [PATCH 717/744] phy: add I2C mdio bus
  5. Add an I2C MDIO bus bridge library, to allow phylib to access PHYs which
  6. are connected to an I2C bus instead of the more conventional MDIO bus.
  7. Such PHYs can be found in SFP adapters and SFF modules.
  8. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
  9. ---
  10. drivers/net/phy/Kconfig | 10 ++++++
  11. drivers/net/phy/Makefile | 1 +
  12. drivers/net/phy/mdio-i2c.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++
  13. drivers/net/phy/mdio-i2c.h | 19 ++++++++++
  14. 4 files changed, 120 insertions(+)
  15. create mode 100644 drivers/net/phy/mdio-i2c.c
  16. create mode 100644 drivers/net/phy/mdio-i2c.h
  17. --- a/drivers/net/phy/Kconfig
  18. +++ b/drivers/net/phy/Kconfig
  19. @@ -233,6 +233,16 @@ config MDIO_GPIO
  20. To compile this driver as a module, choose M here: the module
  21. will be called mdio-gpio.
  22. +config MDIO_I2C
  23. + tristate
  24. + depends on I2C
  25. + help
  26. + Support I2C based PHYs. This provides a MDIO bus bridged
  27. + to I2C to allow PHYs connected in I2C mode to be accessed
  28. + using the existing infrastructure.
  29. +
  30. + This is library mode.
  31. +
  32. config MDIO_OCTEON
  33. tristate "Support for MDIO buses on Octeon and ThunderX SOCs"
  34. depends on 64BIT
  35. --- a/drivers/net/phy/Makefile
  36. +++ b/drivers/net/phy/Makefile
  37. @@ -41,6 +41,7 @@ obj-$(CONFIG_SWCONFIG_B53) += b53/
  38. obj-$(CONFIG_FIXED_PHY) += fixed_phy.o
  39. obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o
  40. obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
  41. +obj-$(CONFIG_MDIO_I2C) += mdio-i2c.o
  42. obj-$(CONFIG_NATIONAL_PHY) += national.o
  43. obj-$(CONFIG_DP83640_PHY) += dp83640.o
  44. obj-$(CONFIG_DP83848_PHY) += dp83848.o
  45. --- /dev/null
  46. +++ b/drivers/net/phy/mdio-i2c.c
  47. @@ -0,0 +1,90 @@
  48. +/*
  49. + * MDIO I2C bridge
  50. + *
  51. + * Copyright (C) 2015 Russell King
  52. + *
  53. + * This program is free software; you can redistribute it and/or modify
  54. + * it under the terms of the GNU General Public License version 2 as
  55. + * published by the Free Software Foundation.
  56. + */
  57. +#include <linux/i2c.h>
  58. +#include <linux/phy.h>
  59. +
  60. +#include "mdio-i2c.h"
  61. +
  62. +static int i2c_mii_read(struct mii_bus *bus, int phy_id, int reg)
  63. +{
  64. + struct i2c_adapter *i2c = bus->priv;
  65. + struct i2c_msg msgs[2];
  66. + u8 data[2], dev_addr = reg;
  67. + int bus_addr, ret;
  68. +
  69. + bus_addr = 0x40 + phy_id;
  70. + if (bus_addr == 0x50 || bus_addr == 0x51)
  71. + return 0xffff;
  72. +
  73. + msgs[0].addr = bus_addr;
  74. + msgs[0].flags = 0;
  75. + msgs[0].len = 1;
  76. + msgs[0].buf = &dev_addr;
  77. + msgs[1].addr = bus_addr;
  78. + msgs[1].flags = I2C_M_RD;
  79. + msgs[1].len = sizeof(data);
  80. + msgs[1].buf = data;
  81. +
  82. + ret = i2c_transfer(i2c, msgs, ARRAY_SIZE(msgs));
  83. + if (ret != ARRAY_SIZE(msgs))
  84. + return 0xffff;
  85. +
  86. + return data[0] << 8 | data[1];
  87. +}
  88. +
  89. +static int i2c_mii_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
  90. +{
  91. + struct i2c_adapter *i2c = bus->priv;
  92. + struct i2c_msg msg;
  93. + int bus_addr, ret;
  94. + u8 data[3];
  95. +
  96. + bus_addr = 0x40 + phy_id;
  97. + if (bus_addr == 0x50 || bus_addr == 0x51)
  98. + return 0;
  99. +
  100. + data[0] = reg;
  101. + data[1] = val >> 8;
  102. + data[2] = val;
  103. +
  104. + msg.addr = bus_addr;
  105. + msg.flags = 0;
  106. + msg.len = 3;
  107. + msg.buf = data;
  108. +
  109. + ret = i2c_transfer(i2c, &msg, 1);
  110. +
  111. + return ret < 0 ? ret : 0;
  112. +}
  113. +
  114. +struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c)
  115. +{
  116. + struct mii_bus *mii;
  117. +
  118. + if (!i2c_check_functionality(i2c, I2C_FUNC_I2C))
  119. + return ERR_PTR(-EINVAL);
  120. +
  121. + mii = mdiobus_alloc();
  122. + if (!mii)
  123. + return ERR_PTR(-ENOMEM);
  124. +
  125. + snprintf(mii->id, MII_BUS_ID_SIZE, "i2c:%s", dev_name(parent));
  126. + mii->parent = parent;
  127. + mii->read = i2c_mii_read;
  128. + mii->write = i2c_mii_write;
  129. + mii->priv = i2c;
  130. +
  131. + return mii;
  132. +}
  133. +EXPORT_SYMBOL_GPL(mdio_i2c_alloc);
  134. +
  135. +MODULE_AUTHOR("Russell King");
  136. +MODULE_DESCRIPTION("MDIO I2C bridge library");
  137. +MODULE_LICENSE("GPL v2");
  138. --- /dev/null
  139. +++ b/drivers/net/phy/mdio-i2c.h
  140. @@ -0,0 +1,19 @@
  141. +/*
  142. + * MDIO I2C bridge
  143. + *
  144. + * Copyright (C) 2015 Russell King
  145. + *
  146. + * This program is free software; you can redistribute it and/or modify
  147. + * it under the terms of the GNU General Public License version 2 as
  148. + * published by the Free Software Foundation.
  149. + */
  150. +#ifndef MDIO_I2C_H
  151. +#define MDIO_I2C_H
  152. +
  153. +struct device;
  154. +struct i2c_adapter;
  155. +struct mii_bus;
  156. +
  157. +struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c);
  158. +
  159. +#endif