1 // SPDX-License-Identifier: GPL-2.0 2 // IOMapped CAN bus driver for Bosch M_CAN controller 3 // Copyright (C) 2014 Freescale Semiconductor, Inc. 4 // Dong Aisheng <b29396@freescale.com> 5 // 6 // Copyright (C) 2018-19 Texas Instruments Incorporated - http://www.ti.com/ 7 8 #include <linux/platform_device.h> 9 #include <linux/phy/phy.h> 10 11 #include "m_can.h" 12 13 struct m_can_plat_priv { 14 struct m_can_classdev cdev; 15 16 void __iomem *base; 17 void __iomem *mram_base; 18 }; 19 20 static inline struct m_can_plat_priv *cdev_to_priv(struct m_can_classdev *cdev) 21 { 22 return container_of(cdev, struct m_can_plat_priv, cdev); 23 } 24 25 static u32 iomap_read_reg(struct m_can_classdev *cdev, int reg) 26 { 27 struct m_can_plat_priv *priv = cdev_to_priv(cdev); 28 29 return readl(priv->base + reg); 30 } 31 32 static int iomap_read_fifo(struct m_can_classdev *cdev, int offset, void *val, size_t val_count) 33 { 34 struct m_can_plat_priv *priv = cdev_to_priv(cdev); 35 36 ioread32_rep(priv->mram_base + offset, val, val_count); 37 38 return 0; 39 } 40 41 static int iomap_write_reg(struct m_can_classdev *cdev, int reg, int val) 42 { 43 struct m_can_plat_priv *priv = cdev_to_priv(cdev); 44 45 writel(val, priv->base + reg); 46 47 return 0; 48 } 49 50 static int iomap_write_fifo(struct m_can_classdev *cdev, int offset, 51 const void *val, size_t val_count) 52 { 53 struct m_can_plat_priv *priv = cdev_to_priv(cdev); 54 55 iowrite32_rep(priv->base + offset, val, val_count); 56 57 return 0; 58 } 59 60 static struct m_can_ops m_can_plat_ops = { 61 .read_reg = iomap_read_reg, 62 .write_reg = iomap_write_reg, 63 .write_fifo = iomap_write_fifo, 64 .read_fifo = iomap_read_fifo, 65 }; 66 67 static int m_can_plat_probe(struct platform_device *pdev) 68 { 69 struct m_can_classdev *mcan_class; 70 struct m_can_plat_priv *priv; 71 struct resource *res; 72 void __iomem *addr; 73 void __iomem *mram_addr; 74 struct phy *transceiver; 75 int irq, ret = 0; 76 77 mcan_class = m_can_class_allocate_dev(&pdev->dev, 78 sizeof(struct m_can_plat_priv)); 79 if (!mcan_class) 80 return -ENOMEM; 81 82 priv = cdev_to_priv(mcan_class); 83 84 ret = m_can_class_get_clocks(mcan_class); 85 if (ret) 86 goto probe_fail; 87 88 addr = devm_platform_ioremap_resource_byname(pdev, "m_can"); 89 irq = platform_get_irq_byname(pdev, "int0"); 90 if (IS_ERR(addr) || irq < 0) { 91 ret = -EINVAL; 92 goto probe_fail; 93 } 94 95 /* message ram could be shared */ 96 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "message_ram"); 97 if (!res) { 98 ret = -ENODEV; 99 goto probe_fail; 100 } 101 102 mram_addr = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 103 if (!mram_addr) { 104 ret = -ENOMEM; 105 goto probe_fail; 106 } 107 108 transceiver = devm_phy_optional_get(&pdev->dev, NULL); 109 if (IS_ERR(transceiver)) { 110 ret = PTR_ERR(transceiver); 111 dev_err_probe(&pdev->dev, ret, "failed to get phy\n"); 112 goto probe_fail; 113 } 114 115 if (transceiver) 116 mcan_class->can.bitrate_max = transceiver->attrs.max_link_rate; 117 118 priv->base = addr; 119 priv->mram_base = mram_addr; 120 121 mcan_class->net->irq = irq; 122 mcan_class->pm_clock_support = 1; 123 mcan_class->can.clock.freq = clk_get_rate(mcan_class->cclk); 124 mcan_class->dev = &pdev->dev; 125 mcan_class->transceiver = transceiver; 126 127 mcan_class->ops = &m_can_plat_ops; 128 129 mcan_class->is_peripheral = false; 130 131 platform_set_drvdata(pdev, mcan_class); 132 133 ret = m_can_init_ram(mcan_class); 134 if (ret) 135 goto probe_fail; 136 137 pm_runtime_enable(mcan_class->dev); 138 ret = m_can_class_register(mcan_class); 139 if (ret) 140 goto out_runtime_disable; 141 142 return ret; 143 144 out_runtime_disable: 145 pm_runtime_disable(mcan_class->dev); 146 probe_fail: 147 m_can_class_free_dev(mcan_class->net); 148 return ret; 149 } 150 151 static __maybe_unused int m_can_suspend(struct device *dev) 152 { 153 return m_can_class_suspend(dev); 154 } 155 156 static __maybe_unused int m_can_resume(struct device *dev) 157 { 158 return m_can_class_resume(dev); 159 } 160 161 static int m_can_plat_remove(struct platform_device *pdev) 162 { 163 struct m_can_plat_priv *priv = platform_get_drvdata(pdev); 164 struct m_can_classdev *mcan_class = &priv->cdev; 165 166 m_can_class_unregister(mcan_class); 167 168 m_can_class_free_dev(mcan_class->net); 169 170 return 0; 171 } 172 173 static int __maybe_unused m_can_runtime_suspend(struct device *dev) 174 { 175 struct m_can_plat_priv *priv = dev_get_drvdata(dev); 176 struct m_can_classdev *mcan_class = &priv->cdev; 177 178 clk_disable_unprepare(mcan_class->cclk); 179 clk_disable_unprepare(mcan_class->hclk); 180 181 return 0; 182 } 183 184 static int __maybe_unused m_can_runtime_resume(struct device *dev) 185 { 186 struct m_can_plat_priv *priv = dev_get_drvdata(dev); 187 struct m_can_classdev *mcan_class = &priv->cdev; 188 int err; 189 190 err = clk_prepare_enable(mcan_class->hclk); 191 if (err) 192 return err; 193 194 err = clk_prepare_enable(mcan_class->cclk); 195 if (err) 196 clk_disable_unprepare(mcan_class->hclk); 197 198 return err; 199 } 200 201 static const struct dev_pm_ops m_can_pmops = { 202 SET_RUNTIME_PM_OPS(m_can_runtime_suspend, 203 m_can_runtime_resume, NULL) 204 SET_SYSTEM_SLEEP_PM_OPS(m_can_suspend, m_can_resume) 205 }; 206 207 static const struct of_device_id m_can_of_table[] = { 208 { .compatible = "bosch,m_can", .data = NULL }, 209 { /* sentinel */ }, 210 }; 211 MODULE_DEVICE_TABLE(of, m_can_of_table); 212 213 static struct platform_driver m_can_plat_driver = { 214 .driver = { 215 .name = KBUILD_MODNAME, 216 .of_match_table = m_can_of_table, 217 .pm = &m_can_pmops, 218 }, 219 .probe = m_can_plat_probe, 220 .remove = m_can_plat_remove, 221 }; 222 223 module_platform_driver(m_can_plat_driver); 224 225 MODULE_AUTHOR("Dong Aisheng <b29396@freescale.com>"); 226 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>"); 227 MODULE_LICENSE("GPL v2"); 228 MODULE_DESCRIPTION("M_CAN driver for IO Mapped Bosch controllers"); 229