diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2019-08-28 07:03:52 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2019-08-28 07:03:52 +0000 |
commit | ea371fa500e1c05b7ed1f4d9422db6751b360c55 (patch) | |
tree | 479093a46c1b470daf5953d13e3316d2e28d2e94 | |
parent | 54ebf385a597f0764bf26dcd5a1c8b764109850a (diff) |
Add a PHY "framework".
ok patrick@
-rw-r--r-- | sys/dev/ofw/ofw_misc.c | 93 | ||||
-rw-r--r-- | sys/dev/ofw/ofw_misc.h | 28 |
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_ */ |