1 // SPDX-License-Identifier: GPL-2.0
3 // Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
4 // Author: Vignesh Raghavendra <vigneshr@ti.com>
7 #include <linux/kernel.h>
8 #include <linux/module.h>
9 #include <linux/mtd/cfi.h>
10 #include <linux/mtd/hyperbus.h>
11 #include <linux/mtd/mtd.h>
12 #include <linux/mux/consumer.h>
14 #include <linux/platform_device.h>
15 #include <linux/pm_runtime.h>
16 #include <linux/types.h>
18 #define AM654_HBMC_CALIB_COUNT 25
20 struct am654_hbmc_priv
{
21 struct hyperbus_ctlr ctlr
;
22 struct hyperbus_device hbdev
;
23 struct mux_control
*mux_ctrl
;
26 static int am654_hbmc_calibrate(struct hyperbus_device
*hbdev
)
28 struct map_info
*map
= &hbdev
->map
;
29 struct cfi_private cfi
;
30 int count
= AM654_HBMC_CALIB_COUNT
;
35 cfi
.device_type
= CFI_DEVICETYPE_X16
;
36 cfi_send_gen_cmd(0xF0, 0, 0, map
, &cfi
, cfi
.device_type
, NULL
);
37 cfi_send_gen_cmd(0x98, 0x55, 0, map
, &cfi
, cfi
.device_type
, NULL
);
40 ret
= cfi_qry_present(map
, 0, &cfi
);
49 cfi_qry_mode_off(0, map
, &cfi
);
54 static const struct hyperbus_ops am654_hbmc_ops
= {
55 .calibrate
= am654_hbmc_calibrate
,
58 static int am654_hbmc_probe(struct platform_device
*pdev
)
60 struct device
*dev
= &pdev
->dev
;
61 struct am654_hbmc_priv
*priv
;
64 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
68 platform_set_drvdata(pdev
, priv
);
70 if (of_property_read_bool(dev
->of_node
, "mux-controls")) {
71 struct mux_control
*control
= devm_mux_control_get(dev
, NULL
);
74 return PTR_ERR(control
);
76 ret
= mux_control_select(control
, 1);
78 dev_err(dev
, "Failed to select HBMC mux\n");
81 priv
->mux_ctrl
= control
;
84 pm_runtime_enable(dev
);
85 ret
= pm_runtime_get_sync(dev
);
87 pm_runtime_put_noidle(dev
);
92 priv
->ctlr
.ops
= &am654_hbmc_ops
;
93 priv
->hbdev
.ctlr
= &priv
->ctlr
;
94 priv
->hbdev
.np
= of_get_next_child(dev
->of_node
, NULL
);
95 ret
= hyperbus_register_device(&priv
->hbdev
);
97 dev_err(dev
, "failed to register controller\n");
98 pm_runtime_put_sync(&pdev
->dev
);
104 pm_runtime_disable(dev
);
106 mux_control_deselect(priv
->mux_ctrl
);
110 static int am654_hbmc_remove(struct platform_device
*pdev
)
112 struct am654_hbmc_priv
*priv
= platform_get_drvdata(pdev
);
115 ret
= hyperbus_unregister_device(&priv
->hbdev
);
117 mux_control_deselect(priv
->mux_ctrl
);
118 pm_runtime_put_sync(&pdev
->dev
);
119 pm_runtime_disable(&pdev
->dev
);
124 static const struct of_device_id am654_hbmc_dt_ids
[] = {
126 .compatible
= "ti,am654-hbmc",
128 { /* end of table */ }
131 MODULE_DEVICE_TABLE(of
, am654_hbmc_dt_ids
);
133 static struct platform_driver am654_hbmc_platform_driver
= {
134 .probe
= am654_hbmc_probe
,
135 .remove
= am654_hbmc_remove
,
137 .name
= "hbmc-am654",
138 .of_match_table
= am654_hbmc_dt_ids
,
142 module_platform_driver(am654_hbmc_platform_driver
);
144 MODULE_DESCRIPTION("HBMC driver for AM654 SoC");
145 MODULE_LICENSE("GPL v2");
146 MODULE_ALIAS("platform:hbmc-am654");
147 MODULE_AUTHOR("Vignesh Raghavendra <vigneshr@ti.com>");