Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.3-rc1 147 lines 3.4 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2// 3// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ 4// Author: Vignesh Raghavendra <vigneshr@ti.com> 5 6#include <linux/err.h> 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> 13#include <linux/of.h> 14#include <linux/platform_device.h> 15#include <linux/pm_runtime.h> 16#include <linux/types.h> 17 18#define AM654_HBMC_CALIB_COUNT 25 19 20struct am654_hbmc_priv { 21 struct hyperbus_ctlr ctlr; 22 struct hyperbus_device hbdev; 23 struct mux_control *mux_ctrl; 24}; 25 26static int am654_hbmc_calibrate(struct hyperbus_device *hbdev) 27{ 28 struct map_info *map = &hbdev->map; 29 struct cfi_private cfi; 30 int count = AM654_HBMC_CALIB_COUNT; 31 int pass_count = 0; 32 int ret; 33 34 cfi.interleave = 1; 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); 38 39 while (count--) { 40 ret = cfi_qry_present(map, 0, &cfi); 41 if (ret) 42 pass_count++; 43 else 44 pass_count = 0; 45 if (pass_count == 5) 46 break; 47 } 48 49 cfi_qry_mode_off(0, map, &cfi); 50 51 return ret; 52} 53 54static const struct hyperbus_ops am654_hbmc_ops = { 55 .calibrate = am654_hbmc_calibrate, 56}; 57 58static int am654_hbmc_probe(struct platform_device *pdev) 59{ 60 struct device *dev = &pdev->dev; 61 struct am654_hbmc_priv *priv; 62 int ret; 63 64 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 65 if (!priv) 66 return -ENOMEM; 67 68 platform_set_drvdata(pdev, priv); 69 70 if (of_property_read_bool(dev->of_node, "mux-controls")) { 71 struct mux_control *control = devm_mux_control_get(dev, NULL); 72 73 if (IS_ERR(control)) 74 return PTR_ERR(control); 75 76 ret = mux_control_select(control, 1); 77 if (ret) { 78 dev_err(dev, "Failed to select HBMC mux\n"); 79 return ret; 80 } 81 priv->mux_ctrl = control; 82 } 83 84 pm_runtime_enable(dev); 85 ret = pm_runtime_get_sync(dev); 86 if (ret < 0) { 87 pm_runtime_put_noidle(dev); 88 goto disable_pm; 89 } 90 91 priv->ctlr.dev = 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); 96 if (ret) { 97 dev_err(dev, "failed to register controller\n"); 98 pm_runtime_put_sync(&pdev->dev); 99 goto disable_pm; 100 } 101 102 return 0; 103disable_pm: 104 pm_runtime_disable(dev); 105 if (priv->mux_ctrl) 106 mux_control_deselect(priv->mux_ctrl); 107 return ret; 108} 109 110static int am654_hbmc_remove(struct platform_device *pdev) 111{ 112 struct am654_hbmc_priv *priv = platform_get_drvdata(pdev); 113 int ret; 114 115 ret = hyperbus_unregister_device(&priv->hbdev); 116 if (priv->mux_ctrl) 117 mux_control_deselect(priv->mux_ctrl); 118 pm_runtime_put_sync(&pdev->dev); 119 pm_runtime_disable(&pdev->dev); 120 121 return ret; 122} 123 124static const struct of_device_id am654_hbmc_dt_ids[] = { 125 { 126 .compatible = "ti,am654-hbmc", 127 }, 128 { /* end of table */ } 129}; 130 131MODULE_DEVICE_TABLE(of, am654_hbmc_dt_ids); 132 133static struct platform_driver am654_hbmc_platform_driver = { 134 .probe = am654_hbmc_probe, 135 .remove = am654_hbmc_remove, 136 .driver = { 137 .name = "hbmc-am654", 138 .of_match_table = am654_hbmc_dt_ids, 139 }, 140}; 141 142module_platform_driver(am654_hbmc_platform_driver); 143 144MODULE_DESCRIPTION("HBMC driver for AM654 SoC"); 145MODULE_LICENSE("GPL v2"); 146MODULE_ALIAS("platform:hbmc-am654"); 147MODULE_AUTHOR("Vignesh Raghavendra <vigneshr@ti.com>");