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>
11 #include <dm/device_compat.h>
13 #define FSS_SYSC_REG 0x4
15 #define HYPERBUS_CALIB_COUNT 25
17 struct am654_hbmc_priv
{
18 void __iomem
*mmiobase
;
22 /* Calibrate by looking for "QRY" string within the CFI space */
23 static int am654_hyperbus_calibrate(struct udevice
*dev
)
25 struct am654_hbmc_priv
*priv
= dev_get_priv(dev
);
26 int count
= HYPERBUS_CALIB_COUNT
;
33 writew(0xF0, priv
->mmiobase
);
34 writew(0x98, priv
->mmiobase
+ 0xaa);
37 qry
[0] = readw(priv
->mmiobase
+ 0x20);
38 qry
[1] = readw(priv
->mmiobase
+ 0x22);
39 qry
[2] = readw(priv
->mmiobase
+ 0x24);
41 if (qry
[0] == 'Q' && qry
[1] == 'R' && qry
[2] == 'Y')
48 writew(0xF0, priv
->mmiobase
);
49 writew(0xFF, priv
->mmiobase
);
51 return pass_count
== 5;
54 static int am654_select_hbmc(struct udevice
*dev
)
56 struct regmap
*regmap
= syscon_get_regmap(dev_get_parent(dev
));
58 return regmap_update_bits(regmap
, FSS_SYSC_REG
, 0x2, 0x2);
61 static int am654_hbmc_bind(struct udevice
*dev
)
63 return dm_scan_fdt_dev(dev
);
66 static int am654_hbmc_probe(struct udevice
*dev
)
68 struct am654_hbmc_priv
*priv
= dev_get_priv(dev
);
71 priv
->mmiobase
= devfdt_remap_addr_index(dev
, 1);
72 if (dev_read_bool(dev
, "mux-controls")) {
73 ret
= am654_select_hbmc(dev
);
75 dev_err(dev
, "Failed to select HBMC mux\n");
80 if (!priv
->calibrated
) {
81 ret
= am654_hyperbus_calibrate(dev
);
83 dev_err(dev
, "Calibration Failed\n");
87 priv
->calibrated
= true;
92 static const struct udevice_id am654_hbmc_dt_ids
[] = {
94 .compatible
= "ti,am654-hbmc",
96 { /* end of table */ }
99 U_BOOT_DRIVER(hbmc_am654
) = {
100 .name
= "hbmc-am654",
102 .of_match
= am654_hbmc_dt_ids
,
103 .probe
= am654_hbmc_probe
,
104 .bind
= am654_hbmc_bind
,
105 .priv_auto
= sizeof(struct am654_hbmc_priv
),