summaryrefslogtreecommitdiff
path: root/sys/dev/ofw
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2019-08-28 07:03:52 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2019-08-28 07:03:52 +0000
commitea371fa500e1c05b7ed1f4d9422db6751b360c55 (patch)
tree479093a46c1b470daf5953d13e3316d2e28d2e94 /sys/dev/ofw
parent54ebf385a597f0764bf26dcd5a1c8b764109850a (diff)
Add a PHY "framework".
ok patrick@
Diffstat (limited to 'sys/dev/ofw')
-rw-r--r--sys/dev/ofw/ofw_misc.c93
-rw-r--r--sys/dev/ofw/ofw_misc.h28
2 files changed, 119 insertions, 2 deletions
diff --git a/sys/dev/ofw/ofw_misc.c b/sys/dev/ofw/ofw_misc.c
index 63f10f34e79..ee8a878bcdb 100644
--- a/sys/dev/ofw/ofw_misc.c
+++ b/sys/dev/ofw/ofw_misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ofw_misc.c,v 1.5 2018/04/02 17:42:15 patrick Exp $ */
+/* $OpenBSD: ofw_misc.c,v 1.6 2019/08/28 07:03:51 kettenis Exp $ */
/*
* Copyright (c) 2017 Mark Kettenis
*
@@ -103,3 +103,94 @@ regmap_read_4(struct regmap *rm, bus_size_t offset)
KASSERT(offset <= rm->rm_size - sizeof(uint32_t));
return bus_space_read_4(rm->rm_tag, rm->rm_handle, offset);
}
+
+
+/*
+ * PHY support.
+ */
+
+LIST_HEAD(, phy_device) phy_devices =
+ LIST_HEAD_INITIALIZER(phy_devices);
+
+void
+phy_register(struct phy_device *pd)
+{
+ pd->pd_cells = OF_getpropint(pd->pd_node, "#phy-cells", 0);
+ pd->pd_phandle = OF_getpropint(pd->pd_node, "phandle", 0);
+ if (pd->pd_phandle == 0)
+ return;
+
+ LIST_INSERT_HEAD(&phy_devices, pd, pd_list);
+}
+
+int
+phy_enable_cells(uint32_t *cells)
+{
+ struct phy_device *pd;
+ uint32_t phandle = cells[0];
+
+ LIST_FOREACH(pd, &phy_devices, pd_list) {
+ if (pd->pd_phandle == phandle)
+ break;
+ }
+
+ if (pd && pd->pd_enable)
+ return pd->pd_enable(pd->pd_cookie, &cells[1]);
+
+ return -1;
+}
+
+uint32_t *
+phy_next_phy(uint32_t *cells)
+{
+ uint32_t phandle = cells[0];
+ int node, ncells;
+
+ node = OF_getnodebyphandle(phandle);
+ if (node == 0)
+ return NULL;
+
+ ncells = OF_getpropint(node, "#phy-cells", 0);
+ return cells + ncells + 1;
+}
+
+int
+phy_enable_idx(int node, int idx)
+{
+ uint32_t *phys;
+ uint32_t *phy;
+ int rv = -1;
+ int len;
+
+ len = OF_getproplen(node, "phys");
+ if (len <= 0)
+ return -1;
+
+ phys = malloc(len, M_TEMP, M_WAITOK);
+ OF_getpropintarray(node, "phys", phys, len);
+
+ phy = phys;
+ while (phy && phy < phys + (len / sizeof(uint32_t))) {
+ if (idx <= 0)
+ rv = phy_enable_cells(phy);
+ if (idx == 0)
+ break;
+ phy = phy_next_phy(phy);
+ idx--;
+ }
+
+ free(phys, M_TEMP, len);
+ return rv;
+}
+
+int
+phy_enable(int node, const char *name)
+{
+ int idx;
+
+ idx = OF_getindex(node, name, "phy-names");
+ if (idx == -1)
+ return -1;
+
+ return phy_enable_idx(node, idx);
+}
diff --git a/sys/dev/ofw/ofw_misc.h b/sys/dev/ofw/ofw_misc.h
index 736ad11a2a7..6cff23281d0 100644
--- a/sys/dev/ofw/ofw_misc.h
+++ b/sys/dev/ofw/ofw_misc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ofw_misc.h,v 1.3 2018/04/02 17:42:15 patrick Exp $ */
+/* $OpenBSD: ofw_misc.h,v 1.4 2019/08/28 07:03:51 kettenis Exp $ */
/*
* Copyright (c) 2017 Mark Kettenis
*
@@ -18,6 +18,8 @@
#ifndef _DEV_OFW_MISC_H_
#define _DEV_OFW_MISC_H_
+/* Register maps */
+
void regmap_register(int, bus_space_tag_t, bus_space_handle_t, bus_size_t);
struct regmap;
@@ -28,4 +30,28 @@ struct regmap *regmap_byphandle(uint32_t);
uint32_t regmap_read_4(struct regmap *, bus_size_t);
void regmap_write_4(struct regmap *, bus_size_t, uint32_t);
+/* PHY support */
+
+#define PHY_NONE 0
+#define PHY_TYPE_SATA 1
+#define PHY_TYPE_PCIE 2
+#define PHY_TYPE_USB2 3
+#define PHY_TYPE_USB3 4
+#define PHY_TYPE_UFS 5
+
+struct phy_device {
+ int pd_node;
+ void *pd_cookie;
+ int (*pd_enable)(void *, uint32_t *);
+
+ LIST_ENTRY(phy_device) pd_list;
+ uint32_t pd_phandle;
+ uint32_t pd_cells;
+};
+
+void phy_register(struct phy_device *);
+
+int phy_enable_idx(int, int);
+int phy_enable(int, const char *);
+
#endif /* _DEV_OFW_MISC_H_ */