aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/clk-uclass.c8
-rw-r--r--drivers/clk/clk_versal.c98
-rw-r--r--drivers/core/of_access.c16
-rw-r--r--drivers/core/ofnode.c89
-rw-r--r--drivers/firmware/firmware-zynqmp.c13
-rw-r--r--drivers/mtd/spi/spi-nor-ids.c1
-rw-r--r--drivers/net/phy/phy.c5
-rw-r--r--drivers/net/xilinx_axi_emac.c50
-rw-r--r--drivers/pinctrl/pinctrl-zynqmp.c15
-rw-r--r--drivers/spi/zynqmp_gqspi.c4
10 files changed, 233 insertions, 66 deletions
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index dc3e9d6a26..f186fcbcdb 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -329,7 +329,13 @@ static int clk_set_default_rates(struct udevice *dev,
dev_dbg(dev,
"could not get assigned clock %d (err = %d)\n",
index, ret);
- continue;
+ /* Skip if it is empty */
+ if (ret == -ENOENT) {
+ ret = 0;
+ continue;
+ }
+
+ return ret;
}
/* This is clk provider device trying to program itself
diff --git a/drivers/clk/clk_versal.c b/drivers/clk/clk_versal.c
index b3b3333123..2e004beca2 100644
--- a/drivers/clk/clk_versal.c
+++ b/drivers/clk/clk_versal.c
@@ -68,6 +68,13 @@
#define CLOCK_NODE_TYPE_DIV 4
#define CLOCK_NODE_TYPE_GATE 6
+#define PM_CLK_REF_CLK (0x830c06aU)
+#define PM_CLK_PL_ALT_REF_CLK (0x830c06bU)
+#define PM_CLK_MUXED_IRO (0x830c06cU)
+#define PM_CLK_EMIO (0x830c071U)
+
+#define TOPOLOGY_TYPE_FIXEDFACTOR 0x3
+
enum clk_type {
CLK_TYPE_OUTPUT,
CLK_TYPE_EXTERNAL,
@@ -365,48 +372,37 @@ static u32 versal_clock_set_div(u32 clk_id, u32 div)
return div;
}
-static u64 versal_clock_ref(u32 clk_id)
+static u64 versal_clock_get_ref_rate(u32 clk_id)
{
- u32 ret_payload[PAYLOAD_ARG_CNT];
- int ref;
-
- xilinx_pm_request(PM_CLOCK_GETPARENT, clk_id, 0, 0, 0, ret_payload);
- ref = ret_payload[0];
- if (!(ref & 1))
+ if (clk_id == PM_CLK_REF_CLK || clk_id == PM_CLK_MUXED_IRO || clk_id == PM_CLK_EMIO)
return ref_clk;
- if (ref & 2)
+ else if (clk_id == PM_CLK_PL_ALT_REF_CLK)
return pl_alt_ref_clk;
- return 0;
+ else
+ return 0;
}
-static u64 versal_clock_get_pll_rate(u32 clk_id)
+static int versal_clock_get_fixed_factor_rate(u32 clock_id, u32 parent_id)
{
+ struct versal_pm_query_data qdata = {0};
u32 ret_payload[PAYLOAD_ARG_CNT];
- u32 fbdiv;
- u32 res;
- u32 frac;
- u64 freq;
- u32 parent_rate, parent_id;
- u32 id = clk_id & 0xFFF;
+ u32 mult, div;
+ u32 parent_rate;
+ int ret;
- xilinx_pm_request(PM_CLOCK_GETSTATE, clk_id, 0, 0, 0, ret_payload);
- res = ret_payload[1];
- if (!res) {
- printf("0%x PLL not enabled\n", clk_id);
- return 0;
- }
+ qdata.qid = PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS;
+ qdata.arg1 = clock_id;
- parent_id = clock[clock[id].parent[0].id].clk_id;
- parent_rate = versal_clock_ref(parent_id);
+ ret = versal_pm_query(qdata, ret_payload);
+ if (ret)
+ return ret;
- xilinx_pm_request(PM_CLOCK_GETDIVIDER, clk_id, 0, 0, 0, ret_payload);
- fbdiv = ret_payload[1];
- xilinx_pm_request(PM_CLOCK_PLL_GETPARAM, clk_id, 2, 0, 0, ret_payload);
- frac = ret_payload[1];
+ mult = ret_payload[1];
+ div = ret_payload[2];
- freq = (fbdiv * parent_rate) >> (1 << frac);
+ parent_rate = versal_clock_get_ref_rate(parent_id);
+ return parent_rate * mult / div;
- return freq;
}
static u32 versal_clock_mux(u32 clk_id)
@@ -437,6 +433,37 @@ static u32 versal_clock_get_parentid(u32 clk_id)
return clock[clock[id].parent[parent_id].id].clk_id;
}
+static u64 versal_clock_get_pll_rate(u32 clk_id)
+{
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+ u32 fbdiv;
+ u32 res;
+ u32 frac;
+ u64 freq;
+ u32 parent_rate, parent_id, parent_ref_clk_id;
+ u32 id = clk_id & 0xFFF;
+
+ xilinx_pm_request(PM_CLOCK_GETSTATE, clk_id, 0, 0, 0, ret_payload);
+ res = ret_payload[1];
+ if (!res) {
+ printf("0%x PLL not enabled\n", clk_id);
+ return 0;
+ }
+
+ parent_id = clock[clock[id].parent[0].id].clk_id;
+ parent_ref_clk_id = versal_clock_get_parentid(parent_id);
+ parent_rate = versal_clock_get_ref_rate(parent_ref_clk_id);
+
+ xilinx_pm_request(PM_CLOCK_GETDIVIDER, clk_id, 0, 0, 0, ret_payload);
+ fbdiv = ret_payload[1];
+ xilinx_pm_request(PM_CLOCK_PLL_GETPARAM, clk_id, 2, 0, 0, ret_payload);
+ frac = ret_payload[1];
+
+ freq = (fbdiv * parent_rate) >> (1 << frac);
+
+ return freq;
+}
+
static u32 versal_clock_gate(u32 clk_id)
{
u32 id = clk_id & 0xFFF;
@@ -479,14 +506,19 @@ static u64 versal_clock_calc(u32 clk_id)
u32 parent_id;
u64 clk_rate;
u32 div;
+ struct clock_topology topology;
if (versal_clock_pll(clk_id, &clk_rate))
return clk_rate;
parent_id = versal_clock_get_parentid(clk_id);
if (((parent_id >> NODE_SUBCLASS_SHIFT) &
- NODE_CLASS_MASK) == NODE_SUBCLASS_CLOCK_REF)
- return versal_clock_ref(clk_id);
+ NODE_CLASS_MASK) == NODE_SUBCLASS_CLOCK_REF) {
+ topology = clock[clk_id & 0x3FF].node[0];
+ if (topology.type == TOPOLOGY_TYPE_FIXEDFACTOR)
+ return versal_clock_get_fixed_factor_rate(clk_id, parent_id);
+ return versal_clock_get_ref_rate(parent_id);
+ }
if (!parent_id)
return 0;
@@ -505,7 +537,7 @@ static int versal_clock_get_rate(u32 clk_id, u64 *clk_rate)
{
if (((clk_id >> NODE_SUBCLASS_SHIFT) &
NODE_CLASS_MASK) == NODE_SUBCLASS_CLOCK_REF)
- *clk_rate = versal_clock_ref(clk_id);
+ *clk_rate = versal_clock_get_ref_rate(clk_id);
if (versal_clock_pll(clk_id, clk_rate))
return 0;
diff --git a/drivers/core/of_access.c b/drivers/core/of_access.c
index 57f10445b1..1bb4d8eab7 100644
--- a/drivers/core/of_access.c
+++ b/drivers/core/of_access.c
@@ -570,26 +570,34 @@ int of_read_u32_index(const struct device_node *np, const char *propname,
return 0;
}
-int of_read_u64(const struct device_node *np, const char *propname, u64 *outp)
+int of_read_u64_index(const struct device_node *np, const char *propname,
+ int index, u64 *outp)
{
const __be64 *val;
debug("%s: %s: ", __func__, propname);
if (!np)
return -EINVAL;
- val = of_find_property_value_of_size(np, propname, sizeof(*outp));
+
+ val = of_find_property_value_of_size(np, propname,
+ sizeof(*outp) * (index + 1));
if (IS_ERR(val)) {
debug("(not found)\n");
return PTR_ERR(val);
}
- *outp = be64_to_cpup(val);
+ *outp = be64_to_cpup(val + index);
debug("%#llx (%lld)\n", (unsigned long long)*outp,
- (unsigned long long)*outp);
+ (unsigned long long)*outp);
return 0;
}
+int of_read_u64(const struct device_node *np, const char *propname, u64 *outp)
+{
+ return of_read_u64_index(np, propname, 0, outp);
+}
+
int of_property_match_string(const struct device_node *np, const char *propname,
const char *string)
{
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index a4dc9bde08..ff0a5b5164 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -344,6 +344,36 @@ int ofnode_read_u32_index(ofnode node, const char *propname, int index,
return 0;
}
+int ofnode_read_u64_index(ofnode node, const char *propname, int index,
+ u64 *outp)
+{
+ const fdt64_t *cell;
+ int len;
+
+ assert(ofnode_valid(node));
+
+ if (ofnode_is_np(node))
+ return of_read_u64_index(ofnode_to_np(node), propname, index,
+ outp);
+
+ cell = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
+ propname, &len);
+ if (!cell) {
+ debug("(not found)\n");
+ return -EINVAL;
+ }
+
+ if (len < (sizeof(u64) * (index + 1))) {
+ debug("(not large enough)\n");
+ return -EOVERFLOW;
+ }
+
+ *outp = fdt64_to_cpu(cell[index]);
+ debug("%#llx (%lld)\n", *outp, *outp);
+
+ return 0;
+}
+
u32 ofnode_read_u32_index_default(ofnode node, const char *propname, int index,
u32 def)
{
@@ -1563,6 +1593,65 @@ const char *ofnode_conf_read_str(const char *prop_name)
return ofnode_read_string(node, prop_name);
}
+int ofnode_read_bootscript_address(u64 *bootscr_address, u64 *bootscr_offset)
+{
+ int ret;
+ ofnode uboot;
+
+ *bootscr_address = 0;
+ *bootscr_offset = 0;
+
+ uboot = ofnode_path("/options/u-boot");
+ if (!ofnode_valid(uboot)) {
+ debug("%s: Missing /u-boot node\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = ofnode_read_u64(uboot, "bootscr-address", bootscr_address);
+ if (ret) {
+ ret = ofnode_read_u64(uboot, "bootscr-ram-offset",
+ bootscr_offset);
+ if (ret)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int ofnode_read_bootscript_flash(u64 *bootscr_flash_offset,
+ u64 *bootscr_flash_size)
+{
+ int ret;
+ ofnode uboot;
+
+ *bootscr_flash_offset = 0;
+ *bootscr_flash_size = 0;
+
+ uboot = ofnode_path("/options/u-boot");
+ if (!ofnode_valid(uboot)) {
+ debug("%s: Missing /u-boot node\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = ofnode_read_u64(uboot, "bootscr-flash-offset",
+ bootscr_flash_offset);
+ if (ret)
+ return -EINVAL;
+
+ ret = ofnode_read_u64(uboot, "bootscr-flash-size",
+ bootscr_flash_size);
+ if (ret)
+ return -EINVAL;
+
+ if (!bootscr_flash_size) {
+ debug("bootscr-flash-size is zero. Ignoring properties!\n");
+ *bootscr_flash_offset = 0;
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
ofnode ofnode_get_phy_node(ofnode node)
{
/* DT node properties that reference a PHY node */
diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c
index ab4c4f1a69..43fb7fa778 100644
--- a/drivers/firmware/firmware-zynqmp.c
+++ b/drivers/firmware/firmware-zynqmp.c
@@ -195,6 +195,19 @@ int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value)
return ret;
}
+int zynqmp_pm_feature(const u32 api_id)
+{
+ int ret;
+ u32 ret_payload[PAYLOAD_ARG_CNT];
+
+ /* Check feature check API version */
+ ret = xilinx_pm_request(PM_FEATURE_CHECK, api_id, 0, 0, 0,
+ ret_payload);
+
+ /* Return feature check version */
+ return ret_payload[1] & FIRMWARE_VERSION_MASK;
+}
+
int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id)
{
int ret;
diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c
index 4587215984..b03dd1cd08 100644
--- a/drivers/mtd/spi/spi-nor-ids.c
+++ b/drivers/mtd/spi/spi-nor-ids.c
@@ -249,6 +249,7 @@ const struct flash_info spi_nor_ids[] = {
{ INFO("mx25u6435f", 0xc22537, 0, 64 * 1024, 128, SECT_4K) },
{ INFO("mx25l12805d", 0xc22018, 0, 64 * 1024, 256, SECT_4K) },
{ INFO("mx25u12835f", 0xc22538, 0, 64 * 1024, 256, SECT_4K) },
+ { INFO("mx25u25635f", 0xc22539, 0, 64 * 1024, 512, SECT_4K) },
{ INFO("mx25u51245g", 0xc2253a, 0, 64 * 1024, 1024, SECT_4K |
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
{ INFO("mx25l12855e", 0xc22618, 0, 64 * 1024, 256, 0) },
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index d50fd505e5..63b3e46f10 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -807,7 +807,10 @@ static struct phy_device *phy_connect_gmii2rgmii(struct mii_dev *bus,
ofnode_for_each_subnode(node, dev_ofnode(dev)) {
node = ofnode_by_compatible(node, "xlnx,gmii-to-rgmii-1.0");
if (ofnode_valid(node)) {
- phydev = phy_device_create(bus, 0,
+ int gmiirgmii_phyaddr;
+
+ gmiirgmii_phyaddr = ofnode_read_u32_default(node, "reg", 0);
+ phydev = phy_device_create(bus, gmiirgmii_phyaddr,
PHY_GMII2RGMII_ID, false);
if (phydev)
phydev->node = node;
diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c
index 39cb3cc260..54f2232768 100644
--- a/drivers/net/xilinx_axi_emac.c
+++ b/drivers/net/xilinx_axi_emac.c
@@ -112,7 +112,7 @@ struct axidma_plat {
int pcsaddr;
int phyaddr;
u8 eth_hasnobuf;
- int phy_of_handle;
+ ofnode phynode;
enum emac_variant mactype;
};
@@ -127,7 +127,7 @@ struct axidma_priv {
struct phy_device *phydev;
struct mii_dev *bus;
u8 eth_hasnobuf;
- int phy_of_handle;
+ ofnode phynode;
enum emac_variant mactype;
};
@@ -335,8 +335,8 @@ static int axiemac_phy_init(struct udevice *dev)
phydev->supported &= supported;
phydev->advertising = phydev->supported;
priv->phydev = phydev;
- if (priv->phy_of_handle)
- priv->phydev->node = offset_to_ofnode(priv->phy_of_handle);
+ if (ofnode_valid(priv->phynode))
+ priv->phydev->node = priv->phynode;
phy_config(phydev);
return 0;
@@ -839,7 +839,7 @@ static int axi_emac_probe(struct udevice *dev)
priv->eth_hasnobuf = plat->eth_hasnobuf;
priv->pcsaddr = plat->pcsaddr;
priv->phyaddr = plat->phyaddr;
- priv->phy_of_handle = plat->phy_of_handle;
+ priv->phynode = plat->phynode;
priv->interface = pdata->phy_interface;
if (IS_ENABLED(CONFIG_DM_ETH_PHY))
@@ -894,20 +894,21 @@ static int axi_emac_of_to_plat(struct udevice *dev)
{
struct axidma_plat *plat = dev_get_plat(dev);
struct eth_pdata *pdata = &plat->eth_pdata;
- int node = dev_of_offset(dev);
- int offset = 0;
+ struct ofnode_phandle_args pcs_node, axistream_node;
+ ofnode phynode;
+ int ret;
pdata->iobase = dev_read_addr(dev);
plat->mactype = dev_get_driver_data(dev);
- offset = fdtdec_lookup_phandle(gd->fdt_blob, node,
- "axistream-connected");
- if (offset <= 0) {
+ ret = dev_read_phandle_with_args(dev, "axistream-connected", NULL, 0, 0,
+ &axistream_node);
+ if (ret) {
printf("%s: axistream is not found\n", __func__);
return -EINVAL;
}
- plat->dmatx = (struct axidma_reg *)fdtdec_get_addr_size_auto_parent
- (gd->fdt_blob, 0, offset, "reg", 0, NULL, false);
+
+ plat->dmatx = (struct axidma_reg *)ofnode_get_addr(axistream_node.node);
if (!plat->dmatx) {
printf("%s: axi_dma register space not found\n", __func__);
return -EINVAL;
@@ -918,30 +919,27 @@ static int axi_emac_of_to_plat(struct udevice *dev)
/* PHYAD 0 always redirects to the PCS/PMA PHY */
plat->pcsaddr = 0;
- offset = fdtdec_lookup_phandle(gd->fdt_blob, node,
- "phy-handle");
- if (offset > 0) {
+ phynode = dev_get_phy_node(dev);
+ if (ofnode_valid(phynode)) {
if (!(IS_ENABLED(CONFIG_DM_ETH_PHY)))
- plat->phyaddr = fdtdec_get_int(gd->fdt_blob,
- offset,
- "reg", -1);
- plat->phy_of_handle = offset;
+ plat->phyaddr = ofnode_read_u32_default(phynode,
+ "reg", -1);
+ plat->phynode = phynode;
}
pdata->phy_interface = dev_read_phy_mode(dev);
if (pdata->phy_interface == PHY_INTERFACE_MODE_NA)
return -EINVAL;
- plat->eth_hasnobuf = fdtdec_get_bool(gd->fdt_blob, node,
- "xlnx,eth-hasnobuf");
+ plat->eth_hasnobuf = dev_read_bool(dev, "xlnx,eth-hasnobuf");
if (pdata->phy_interface == PHY_INTERFACE_MODE_SGMII ||
pdata->phy_interface == PHY_INTERFACE_MODE_1000BASEX) {
- offset = fdtdec_lookup_phandle(gd->fdt_blob, node,
- "pcs-handle");
- if (offset > 0) {
- plat->pcsaddr = fdtdec_get_int(gd->fdt_blob,
- offset, "reg", -1);
+ ret = dev_read_phandle_with_args(dev, "pcs-handle", NULL, 0, 0,
+ &pcs_node);
+ if (!ret) {
+ plat->pcsaddr = ofnode_read_u32_default(pcs_node.node,
+ "reg", -1);
}
}
}
diff --git a/drivers/pinctrl/pinctrl-zynqmp.c b/drivers/pinctrl/pinctrl-zynqmp.c
index 02626a7561..517035961d 100644
--- a/drivers/pinctrl/pinctrl-zynqmp.c
+++ b/drivers/pinctrl/pinctrl-zynqmp.c
@@ -158,6 +158,12 @@ static int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param, u32 valu
{
int ret;
+ if (param == PM_PINCTRL_CONFIG_TRI_STATE) {
+ ret = zynqmp_pm_feature(PM_PINCTRL_CONFIG_PARAM_SET);
+ if (ret < PM_PINCTRL_PARAM_SET_VERSION)
+ return -EOPNOTSUPP;
+ }
+
/* Request the pin first */
ret = xilinx_pm_request(PM_PINCTRL_REQUEST, pin, 0, 0, 0, NULL);
if (ret) {
@@ -467,6 +473,10 @@ static int zynqmp_pinconf_set(struct udevice *dev, unsigned int pin,
pin);
break;
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
+ param = PM_PINCTRL_CONFIG_TRI_STATE;
+ arg = PM_PINCTRL_TRI_STATE_ENABLE;
+ ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
+ break;
case PIN_CONFIG_LOW_POWER_MODE:
/*
* This cases are mentioned in dts but configurable
@@ -475,6 +485,11 @@ static int zynqmp_pinconf_set(struct udevice *dev, unsigned int pin,
*/
ret = 0;
break;
+ case PIN_CONFIG_OUTPUT_ENABLE:
+ param = PM_PINCTRL_CONFIG_TRI_STATE;
+ arg = PM_PINCTRL_TRI_STATE_DISABLE;
+ ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
+ break;
default:
dev_warn(dev, "unsupported configuration parameter '%u'\n",
param);
diff --git a/drivers/spi/zynqmp_gqspi.c b/drivers/spi/zynqmp_gqspi.c
index c4aee279aa..ec59ef5804 100644
--- a/drivers/spi/zynqmp_gqspi.c
+++ b/drivers/spi/zynqmp_gqspi.c
@@ -690,7 +690,7 @@ static int zynqmp_qspi_start_dma(struct zynqmp_qspi_priv *priv,
writel(GQSPI_DMA_DST_I_STS_MASK, &dma_regs->dmaier);
addr = (unsigned long)buf;
size = roundup(priv->len, GQSPI_DMA_ALIGN);
- flush_dcache_range(addr, addr + size);
+ invalidate_dcache_range(addr, addr + size);
while (priv->len) {
zynqmp_qspi_calc_exp(priv, &gen_fifo_cmd);
@@ -707,6 +707,8 @@ static int zynqmp_qspi_start_dma(struct zynqmp_qspi_priv *priv,
return -ETIMEDOUT;
}
+ invalidate_dcache_range(addr, addr + size);
+
writel(GQSPI_DMA_DST_I_STS_DONE, &dma_regs->dmaisr);
debug("buf:0x%lx, rxbuf:0x%lx, *buf:0x%x len: 0x%x\n",