new file mode 100644
@@ -0,0 +1,26 @@
+Ethernet Phy fixup Device Tree Bindings
+---------------------------------------
+
+The following DT fields can be added to MDIO DT notes and can be used to
+add phy fix up needed
+
+Required properties:
+- phy-fixup-registers : Will contain a array of register fix nodes which has
+ the following node parameters
+- phy-id : Specifies the phy id for which the fix belongs to
+- phy-mask : Specifies the phy mask for which the fix belongs to
+- fixup-registers : Specifies the fix up registers and values in array
+ of offset value pair
+Optional properties:
+
+Examples:
+
+&davinci_mdio {
+ phy-fixup-registers = <&atheros_txclk_delay_fixup>;
+
+ atheros_txclk_delay_fixup: atheros_txclk_delay_fixup {
+ phy-id = <0x4dd074>;
+ phy-mask = <0xfffffffe>;
+ fixup-registers = <0x1d 0x5 0x1e 0x100>;
+ };
+};
@@ -10,6 +10,7 @@
#include <linux/of_net.h>
#include <linux/phy.h>
#include <linux/export.h>
+#include <linux/of_net.h>
/**
* It maps 'enum phy_interface_t' found in include/linux/phy.h
@@ -92,3 +93,94 @@ const void *of_get_mac_address(struct device_node *np)
return NULL;
}
EXPORT_SYMBOL(of_get_mac_address);
+
+static int __of_phy_fixup_cb(struct phy_device *phydev)
+{
+ struct device_node *node = phydev->bus->parent->of_node;
+ struct device_node *phy_fixup_node;
+ const __be32 *parp;
+ int lenp;
+ int i, j;
+
+ parp = of_get_property(node, "phy-fixup-registers", &lenp);
+ if (parp == NULL)
+ return 0;
+ lenp /= sizeof(void *);
+
+ for (i = 0; i < lenp; i++) {
+ u32 phy_id;
+ const __be32 *fixups;
+ int fixup_len;
+
+ phy_fixup_node = of_find_node_by_phandle(be32_to_cpup(parp+i));
+ if (of_property_read_u32(phy_fixup_node, "phy-id", &phy_id)) {
+ pr_err("Missing PHY id in Phy fixup\n");
+ return -EINVAL;
+ }
+ if (phy_id != phydev->phy_id)
+ continue;
+
+ fixups = of_get_property(phy_fixup_node, "fixup-registers",
+ &fixup_len);
+ if (fixups == NULL) {
+ pr_err("Missing fixup registers in Phy fixup\n");
+ return -EINVAL;
+ }
+ fixup_len /= sizeof(void *);
+ for (j = 0; j < fixup_len; j += 2) {
+ u16 regnum = be32_to_cpup(fixups + j);
+ u16 val = be32_to_cpup(fixups + j + 1);
+ phy_write(phydev, regnum, val);
+ }
+ }
+
+ return 0;
+}
+
+int of_add_phy_fixup_register(struct device_node *node)
+{
+ struct device_node *phy_fixup_node;
+ const __be32 *parp;
+ int lenp;
+ int i;
+
+ parp = of_get_property(node, "phy-fixup-registers", &lenp);
+ if (parp == NULL)
+ return 0;
+ lenp /= sizeof(void *);
+
+ for (i = 0; i < lenp; i++) {
+ u32 phy_id;
+ u32 phy_mask;
+ const __be32 *fixups;
+ int fixup_len;
+
+ phy_fixup_node = of_find_node_by_phandle(be32_to_cpup(parp+i));
+ if (of_property_read_u32(phy_fixup_node, "phy-id", &phy_id)) {
+ pr_err("Missing PHY id in Phy fixup\n");
+ continue;
+ }
+
+ if (of_property_read_u32(phy_fixup_node, "phy-mask",
+ &phy_mask)) {
+ pr_err("Missing PHY mask in Phy fixup\n");
+ continue;
+ }
+
+ fixups = of_get_property(phy_fixup_node, "fixup-registers",
+ &fixup_len);
+ if (fixups == NULL) {
+ pr_err("Missing fixup registers in Phy fixup\n");
+ continue;
+ }
+ fixup_len /= sizeof(void *);
+ if (fixup_len % 2) {
+ pr_err("Fixup registers length is invalid in Phy fixup\n");
+ continue;
+ }
+ phy_register_fixup_for_uid(phy_id, phy_mask, __of_phy_fixup_cb);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_add_phy_fixup_register);
@@ -11,6 +11,7 @@
#include <linux/of.h>
extern const int of_get_phy_mode(struct device_node *np);
extern const void *of_get_mac_address(struct device_node *np);
+extern int of_add_phy_fixup_register(struct device_node *node);
#else
static inline const int of_get_phy_mode(struct device_node *np)
{
@@ -21,6 +22,11 @@ static inline const void *of_get_mac_address(struct device_node *np)
{
return NULL;
}
+
+static int of_add_phy_fixup_register(struct device_node *node)
+{
+ return -ENODEV;
+}
#endif
#endif /* __LINUX_OF_NET_H */
In earlier case phy fixup are added in board file as this is no more the case so adding support for phy register fixup in Device Tree Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com> --- .../devicetree/bindings/net/phy-fixup.txt | 26 ++++++ drivers/of/of_net.c | 92 ++++++++++++++++++++ include/linux/of_net.h | 6 ++ 3 files changed, 124 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/phy-fixup.txt