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>
6 // Copyright (C) 2018-19 Texas Instruments Incorporated - http://www.ti.com/
8 #include <linux/hrtimer.h>
9 #include <linux/phy/phy.h>
10 #include <linux/platform_device.h>
14 struct m_can_plat_priv
{
15 struct m_can_classdev cdev
;
18 void __iomem
*mram_base
;
21 static inline struct m_can_plat_priv
*cdev_to_priv(struct m_can_classdev
*cdev
)
23 return container_of(cdev
, struct m_can_plat_priv
, cdev
);
26 static u32
iomap_read_reg(struct m_can_classdev
*cdev
, int reg
)
28 struct m_can_plat_priv
*priv
= cdev_to_priv(cdev
);
30 return readl(priv
->base
+ reg
);
33 static int iomap_read_fifo(struct m_can_classdev
*cdev
, int offset
, void *val
, size_t val_count
)
35 struct m_can_plat_priv
*priv
= cdev_to_priv(cdev
);
36 void __iomem
*src
= priv
->mram_base
+ offset
;
39 *(unsigned int *)val
= ioread32(src
);
47 static int iomap_write_reg(struct m_can_classdev
*cdev
, int reg
, int val
)
49 struct m_can_plat_priv
*priv
= cdev_to_priv(cdev
);
51 writel(val
, priv
->base
+ reg
);
56 static int iomap_write_fifo(struct m_can_classdev
*cdev
, int offset
,
57 const void *val
, size_t val_count
)
59 struct m_can_plat_priv
*priv
= cdev_to_priv(cdev
);
60 void __iomem
*dst
= priv
->mram_base
+ offset
;
63 iowrite32(*(unsigned int *)val
, dst
);
71 static const struct m_can_ops m_can_plat_ops
= {
72 .read_reg
= iomap_read_reg
,
73 .write_reg
= iomap_write_reg
,
74 .write_fifo
= iomap_write_fifo
,
75 .read_fifo
= iomap_read_fifo
,
78 static int m_can_plat_probe(struct platform_device
*pdev
)
80 struct m_can_classdev
*mcan_class
;
81 struct m_can_plat_priv
*priv
;
84 void __iomem
*mram_addr
;
85 struct phy
*transceiver
;
88 mcan_class
= m_can_class_allocate_dev(&pdev
->dev
,
89 sizeof(struct m_can_plat_priv
));
93 priv
= cdev_to_priv(mcan_class
);
95 ret
= m_can_class_get_clocks(mcan_class
);
99 addr
= devm_platform_ioremap_resource_byname(pdev
, "m_can");
105 if (device_property_present(mcan_class
->dev
, "interrupts") ||
106 device_property_present(mcan_class
->dev
, "interrupt-names")) {
107 irq
= platform_get_irq_byname(pdev
, "int0");
114 /* message ram could be shared */
115 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "message_ram");
121 mram_addr
= devm_ioremap(&pdev
->dev
, res
->start
, resource_size(res
));
127 transceiver
= devm_phy_optional_get(&pdev
->dev
, NULL
);
128 if (IS_ERR(transceiver
)) {
129 ret
= PTR_ERR(transceiver
);
130 dev_err_probe(&pdev
->dev
, ret
, "failed to get phy\n");
135 mcan_class
->can
.bitrate_max
= transceiver
->attrs
.max_link_rate
;
138 priv
->mram_base
= mram_addr
;
140 mcan_class
->net
->irq
= irq
;
141 mcan_class
->pm_clock_support
= 1;
142 mcan_class
->pm_wake_source
= 0;
143 mcan_class
->can
.clock
.freq
= clk_get_rate(mcan_class
->cclk
);
144 mcan_class
->dev
= &pdev
->dev
;
145 mcan_class
->transceiver
= transceiver
;
147 mcan_class
->ops
= &m_can_plat_ops
;
149 mcan_class
->is_peripheral
= false;
151 platform_set_drvdata(pdev
, mcan_class
);
153 pm_runtime_enable(mcan_class
->dev
);
154 ret
= m_can_class_register(mcan_class
);
156 goto out_runtime_disable
;
161 pm_runtime_disable(mcan_class
->dev
);
163 m_can_class_free_dev(mcan_class
->net
);
167 static __maybe_unused
int m_can_suspend(struct device
*dev
)
169 return m_can_class_suspend(dev
);
172 static __maybe_unused
int m_can_resume(struct device
*dev
)
174 return m_can_class_resume(dev
);
177 static void m_can_plat_remove(struct platform_device
*pdev
)
179 struct m_can_plat_priv
*priv
= platform_get_drvdata(pdev
);
180 struct m_can_classdev
*mcan_class
= &priv
->cdev
;
182 m_can_class_unregister(mcan_class
);
184 m_can_class_free_dev(mcan_class
->net
);
187 static int __maybe_unused
m_can_runtime_suspend(struct device
*dev
)
189 struct m_can_plat_priv
*priv
= dev_get_drvdata(dev
);
190 struct m_can_classdev
*mcan_class
= &priv
->cdev
;
192 clk_disable_unprepare(mcan_class
->cclk
);
193 clk_disable_unprepare(mcan_class
->hclk
);
198 static int __maybe_unused
m_can_runtime_resume(struct device
*dev
)
200 struct m_can_plat_priv
*priv
= dev_get_drvdata(dev
);
201 struct m_can_classdev
*mcan_class
= &priv
->cdev
;
204 err
= clk_prepare_enable(mcan_class
->hclk
);
208 err
= clk_prepare_enable(mcan_class
->cclk
);
210 clk_disable_unprepare(mcan_class
->hclk
);
215 static const struct dev_pm_ops m_can_pmops
= {
216 SET_RUNTIME_PM_OPS(m_can_runtime_suspend
,
217 m_can_runtime_resume
, NULL
)
218 SET_SYSTEM_SLEEP_PM_OPS(m_can_suspend
, m_can_resume
)
221 static const struct of_device_id m_can_of_table
[] = {
222 { .compatible
= "bosch,m_can", .data
= NULL
},
225 MODULE_DEVICE_TABLE(of
, m_can_of_table
);
227 static struct platform_driver m_can_plat_driver
= {
229 .name
= KBUILD_MODNAME
,
230 .of_match_table
= m_can_of_table
,
233 .probe
= m_can_plat_probe
,
234 .remove
= m_can_plat_remove
,
237 module_platform_driver(m_can_plat_driver
);
239 MODULE_AUTHOR("Dong Aisheng <b29396@freescale.com>");
240 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
241 MODULE_LICENSE("GPL v2");
242 MODULE_DESCRIPTION("M_CAN driver for IO Mapped Bosch controllers");