xref: /linux/drivers/net/can/dummy_can.c (revision 362d051c90b6e27b01dceed8c47ddfc86e60db2c)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 /* Copyright (c) 2025 Vincent Mailhol <mailhol@kernel.org> */
4 
5 #include <linux/array_size.h>
6 #include <linux/errno.h>
7 #include <linux/init.h>
8 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/netdevice.h>
11 #include <linux/units.h>
12 #include <linux/string_choices.h>
13 
14 #include <linux/can.h>
15 #include <linux/can/bittiming.h>
16 #include <linux/can/dev.h>
17 #include <linux/can/skb.h>
18 
19 struct dummy_can {
20 	struct can_priv can;
21 	struct net_device *dev;
22 };
23 
24 static struct dummy_can *dummy_can;
25 
26 static const struct can_bittiming_const dummy_can_bittiming_const = {
27 	.name = "dummy_can CC",
28 	.tseg1_min = 2,
29 	.tseg1_max = 256,
30 	.tseg2_min = 2,
31 	.tseg2_max = 128,
32 	.sjw_max = 128,
33 	.brp_min = 1,
34 	.brp_max = 512,
35 	.brp_inc = 1
36 };
37 
38 static const struct can_bittiming_const dummy_can_fd_databittiming_const = {
39 	.name = "dummy_can FD",
40 	.tseg1_min = 2,
41 	.tseg1_max = 256,
42 	.tseg2_min = 2,
43 	.tseg2_max = 128,
44 	.sjw_max = 128,
45 	.brp_min = 1,
46 	.brp_max = 512,
47 	.brp_inc = 1
48 };
49 
50 static const struct can_tdc_const dummy_can_fd_tdc_const = {
51 	.tdcv_min = 0,
52 	.tdcv_max = 0, /* Manual mode not supported. */
53 	.tdco_min = 0,
54 	.tdco_max = 127,
55 	.tdcf_min = 0,
56 	.tdcf_max = 127
57 };
58 
59 static const struct can_bittiming_const dummy_can_xl_databittiming_const = {
60 	.name = "dummy_can XL",
61 	.tseg1_min = 2,
62 	.tseg1_max = 256,
63 	.tseg2_min = 2,
64 	.tseg2_max = 128,
65 	.sjw_max = 128,
66 	.brp_min = 1,
67 	.brp_max = 512,
68 	.brp_inc = 1
69 };
70 
71 static const struct can_tdc_const dummy_can_xl_tdc_const = {
72 	.tdcv_min = 0,
73 	.tdcv_max = 0, /* Manual mode not supported. */
74 	.tdco_min = 0,
75 	.tdco_max = 127,
76 	.tdcf_min = 0,
77 	.tdcf_max = 127
78 };
79 
80 static const struct can_pwm_const dummy_can_pwm_const = {
81 	.pwms_min = 1,
82 	.pwms_max = 8,
83 	.pwml_min = 2,
84 	.pwml_max = 24,
85 	.pwmo_min = 0,
86 	.pwmo_max = 16,
87 };
88 
89 static void dummy_can_print_bittiming(struct net_device *dev,
90 				      struct can_bittiming *bt)
91 {
92 	netdev_dbg(dev, "\tbitrate: %u\n", bt->bitrate);
93 	netdev_dbg(dev, "\tsample_point: %u\n", bt->sample_point);
94 	netdev_dbg(dev, "\ttq: %u\n", bt->tq);
95 	netdev_dbg(dev, "\tprop_seg: %u\n", bt->prop_seg);
96 	netdev_dbg(dev, "\tphase_seg1: %u\n", bt->phase_seg1);
97 	netdev_dbg(dev, "\tphase_seg2: %u\n", bt->phase_seg2);
98 	netdev_dbg(dev, "\tsjw: %u\n", bt->sjw);
99 	netdev_dbg(dev, "\tbrp: %u\n", bt->brp);
100 }
101 
102 static void dummy_can_print_tdc(struct net_device *dev, struct can_tdc *tdc)
103 {
104 	netdev_dbg(dev, "\t\ttdcv: %u\n", tdc->tdcv);
105 	netdev_dbg(dev, "\t\ttdco: %u\n", tdc->tdco);
106 	netdev_dbg(dev, "\t\ttdcf: %u\n", tdc->tdcf);
107 }
108 
109 static void dummy_can_print_pwm(struct net_device *dev, struct can_pwm *pwm,
110 				struct can_bittiming *dbt)
111 {
112 	netdev_dbg(dev, "\t\tpwms: %u\n", pwm->pwms);
113 	netdev_dbg(dev, "\t\tpwml: %u\n", pwm->pwml);
114 	netdev_dbg(dev, "\t\tpwmo: %u\n", pwm->pwmo);
115 }
116 
117 static void dummy_can_print_ctrlmode(struct net_device *dev)
118 {
119 	struct dummy_can *priv = netdev_priv(dev);
120 	struct can_priv *can_priv = &priv->can;
121 	unsigned long supported = can_priv->ctrlmode_supported;
122 	u32 enabled = can_priv->ctrlmode;
123 
124 	netdev_dbg(dev, "Control modes:\n");
125 	netdev_dbg(dev, "\tsupported: 0x%08x\n", (u32)supported);
126 	netdev_dbg(dev, "\tenabled: 0x%08x\n", enabled);
127 
128 	if (supported) {
129 		int idx;
130 
131 		netdev_dbg(dev, "\tlist:");
132 		for_each_set_bit(idx, &supported, BITS_PER_TYPE(u32))
133 			netdev_dbg(dev, "\t\t%s: %s\n",
134 				   can_get_ctrlmode_str(BIT(idx)),
135 				   enabled & BIT(idx) ? "on" : "off");
136 	}
137 }
138 
139 static void dummy_can_print_bittiming_info(struct net_device *dev)
140 {
141 	struct dummy_can *priv = netdev_priv(dev);
142 	struct can_priv *can_priv = &priv->can;
143 
144 	netdev_dbg(dev, "Clock frequency: %u\n", can_priv->clock.freq);
145 	netdev_dbg(dev, "Maximum bitrate: %u\n", can_priv->bitrate_max);
146 	netdev_dbg(dev, "MTU: %u\n", dev->mtu);
147 	netdev_dbg(dev, "\n");
148 
149 	dummy_can_print_ctrlmode(dev);
150 	netdev_dbg(dev, "\n");
151 
152 	netdev_dbg(dev, "Classical CAN nominal bittiming:\n");
153 	dummy_can_print_bittiming(dev, &can_priv->bittiming);
154 	netdev_dbg(dev, "\n");
155 
156 	if (can_priv->ctrlmode & CAN_CTRLMODE_FD) {
157 		netdev_dbg(dev, "CAN FD databittiming:\n");
158 		dummy_can_print_bittiming(dev, &can_priv->fd.data_bittiming);
159 		if (can_fd_tdc_is_enabled(can_priv)) {
160 			netdev_dbg(dev, "\tCAN FD TDC:\n");
161 			dummy_can_print_tdc(dev, &can_priv->fd.tdc);
162 		}
163 	}
164 	netdev_dbg(dev, "\n");
165 
166 	if (can_priv->ctrlmode & CAN_CTRLMODE_XL) {
167 		netdev_dbg(dev, "CAN XL databittiming:\n");
168 		dummy_can_print_bittiming(dev, &can_priv->xl.data_bittiming);
169 		if (can_xl_tdc_is_enabled(can_priv)) {
170 			netdev_dbg(dev, "\tCAN XL TDC:\n");
171 			dummy_can_print_tdc(dev, &can_priv->xl.tdc);
172 		}
173 		if (can_priv->ctrlmode & CAN_CTRLMODE_XL_TMS) {
174 			netdev_dbg(dev, "\tCAN XL PWM:\n");
175 			dummy_can_print_pwm(dev, &can_priv->xl.pwm,
176 					    &can_priv->xl.data_bittiming);
177 		}
178 	}
179 	netdev_dbg(dev, "\n");
180 }
181 
182 static int dummy_can_netdev_open(struct net_device *dev)
183 {
184 	int ret;
185 	struct can_priv *priv = netdev_priv(dev);
186 
187 	dummy_can_print_bittiming_info(dev);
188 	netdev_dbg(dev, "error-signalling is %s\n",
189 		   str_enabled_disabled(!can_dev_in_xl_only_mode(priv)));
190 
191 	ret = open_candev(dev);
192 	if (ret)
193 		return ret;
194 	netif_start_queue(dev);
195 	netdev_dbg(dev, "dummy-can is up\n");
196 
197 	return 0;
198 }
199 
200 static int dummy_can_netdev_close(struct net_device *dev)
201 {
202 	netif_stop_queue(dev);
203 	close_candev(dev);
204 	netdev_dbg(dev, "dummy-can is down\n");
205 
206 	return 0;
207 }
208 
209 static netdev_tx_t dummy_can_start_xmit(struct sk_buff *skb,
210 					struct net_device *dev)
211 {
212 	if (can_dev_dropped_skb(dev, skb))
213 		return NETDEV_TX_OK;
214 
215 	can_put_echo_skb(skb, dev, 0, 0);
216 	dev->stats.tx_packets++;
217 	dev->stats.tx_bytes += can_get_echo_skb(dev, 0, NULL);
218 
219 	return NETDEV_TX_OK;
220 }
221 
222 static const struct net_device_ops dummy_can_netdev_ops = {
223 	.ndo_open = dummy_can_netdev_open,
224 	.ndo_stop = dummy_can_netdev_close,
225 	.ndo_start_xmit = dummy_can_start_xmit,
226 };
227 
228 static const struct ethtool_ops dummy_can_ethtool_ops = {
229 	.get_ts_info = ethtool_op_get_ts_info,
230 };
231 
232 static int __init dummy_can_init(void)
233 {
234 	struct net_device *dev;
235 	struct dummy_can *priv;
236 	int ret;
237 
238 	dev = alloc_candev(sizeof(*priv), 1);
239 	if (!dev)
240 		return -ENOMEM;
241 
242 	dev->netdev_ops = &dummy_can_netdev_ops;
243 	dev->ethtool_ops = &dummy_can_ethtool_ops;
244 	priv = netdev_priv(dev);
245 	priv->can.bittiming_const = &dummy_can_bittiming_const;
246 	priv->can.bitrate_max = 20 * MEGA /* BPS */;
247 	priv->can.clock.freq = 160 * MEGA /* Hz */;
248 	priv->can.fd.data_bittiming_const = &dummy_can_fd_databittiming_const;
249 	priv->can.fd.tdc_const = &dummy_can_fd_tdc_const;
250 	priv->can.xl.data_bittiming_const = &dummy_can_xl_databittiming_const;
251 	priv->can.xl.tdc_const = &dummy_can_xl_tdc_const;
252 	priv->can.xl.pwm_const = &dummy_can_pwm_const;
253 	priv->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY |
254 		CAN_CTRLMODE_FD | CAN_CTRLMODE_TDC_AUTO |
255 		CAN_CTRLMODE_RESTRICTED | CAN_CTRLMODE_XL |
256 		CAN_CTRLMODE_XL_TDC_AUTO | CAN_CTRLMODE_XL_TMS;
257 	priv->dev = dev;
258 
259 	ret = register_candev(priv->dev);
260 	if (ret) {
261 		free_candev(priv->dev);
262 		return ret;
263 	}
264 
265 	dummy_can = priv;
266 	netdev_dbg(dev, "dummy-can ready\n");
267 
268 	return 0;
269 }
270 
271 static void __exit dummy_can_exit(void)
272 {
273 	struct net_device *dev = dummy_can->dev;
274 
275 	netdev_dbg(dev, "dummy-can bye bye\n");
276 	unregister_candev(dev);
277 	free_candev(dev);
278 }
279 
280 module_init(dummy_can_init);
281 module_exit(dummy_can_exit);
282 
283 MODULE_DESCRIPTION("A dummy CAN driver, mainly to test the netlink interface");
284 MODULE_LICENSE("GPL");
285 MODULE_AUTHOR("Vincent Mailhol <mailhol@kernel.org>");
286