1 // SPDX-License-Identifier: GPL-2.0
3 // Copyright (C) 2019 Texas Instruments Incorporated - https://www.ti.com/
4 // Author: Vignesh Raghavendra <vigneshr@ti.com>
10 #include <dm/device_compat.h>
12 #define FSS_SYSC_REG 0x4
14 #define HYPERBUS_CALIB_COUNT 25
16 struct am654_hbmc_priv {
17 void __iomem *mmiobase;
21 /* Calibrate by looking for "QRY" string within the CFI space */
22 static int am654_hyperbus_calibrate(struct udevice *dev)
24 struct am654_hbmc_priv *priv = dev_get_priv(dev);
25 int count = HYPERBUS_CALIB_COUNT;
32 writew(0xF0, priv->mmiobase);
33 writew(0x98, priv->mmiobase + 0xaa);
36 qry[0] = readw(priv->mmiobase + 0x20);
37 qry[1] = readw(priv->mmiobase + 0x22);
38 qry[2] = readw(priv->mmiobase + 0x24);
40 if (qry[0] == 'Q' && qry[1] == 'R' && qry[2] == 'Y')
47 writew(0xF0, priv->mmiobase);
48 writew(0xFF, priv->mmiobase);
50 return pass_count == 5;
53 static int am654_select_hbmc(struct udevice *dev)
55 struct mux_control *mux_ctl;
58 ret = mux_get_by_index(dev, 0, &mux_ctl);
60 ret = mux_control_select(mux_ctl, 1);
64 static int am654_hbmc_bind(struct udevice *dev)
66 return dm_scan_fdt_dev(dev);
69 static int am654_hbmc_probe(struct udevice *dev)
71 struct am654_hbmc_priv *priv = dev_get_priv(dev);
74 priv->mmiobase = devfdt_remap_addr_index(dev, 1);
75 if (dev_read_bool(dev, "mux-controls")) {
76 ret = am654_select_hbmc(dev);
78 dev_err(dev, "Failed to select HBMC mux\n");
83 if (!priv->calibrated) {
84 ret = am654_hyperbus_calibrate(dev);
86 dev_err(dev, "Calibration Failed\n");
90 priv->calibrated = true;
95 static const struct udevice_id am654_hbmc_dt_ids[] = {
97 .compatible = "ti,am654-hbmc",
99 { /* end of table */ }
102 U_BOOT_DRIVER(hbmc_am654) = {
103 .name = "hbmc-am654",
105 .of_match = am654_hbmc_dt_ids,
106 .probe = am654_hbmc_probe,
107 .bind = am654_hbmc_bind,
108 .priv_auto = sizeof(struct am654_hbmc_priv),