7
7
#define TCAN4X5X_EXT_CLK_DEF 40000000
8
8
9
9
#define TCAN4X5X_DEV_ID1 0x00
10
+ #define TCAN4X5X_DEV_ID1_TCAN 0x4e414354 /* ASCII TCAN */
10
11
#define TCAN4X5X_DEV_ID2 0x04
11
12
#define TCAN4X5X_REV 0x08
12
13
#define TCAN4X5X_STATUS 0x0C
103
104
#define TCAN4X5X_WD_3_S_TIMER BIT(29)
104
105
#define TCAN4X5X_WD_6_S_TIMER (BIT(28) | BIT(29))
105
106
107
+ struct tcan4x5x_version_info {
108
+ const char * name ;
109
+ u32 id2_register ;
110
+
111
+ bool has_wake_pin ;
112
+ bool has_state_pin ;
113
+ };
114
+
115
+ enum {
116
+ TCAN4552 = 0 ,
117
+ TCAN4553 ,
118
+ TCAN4X5X ,
119
+ };
120
+
121
+ static const struct tcan4x5x_version_info tcan4x5x_versions [] = {
122
+ [TCAN4552 ] = {
123
+ .name = "4552" ,
124
+ .id2_register = 0x32353534 ,
125
+ },
126
+ [TCAN4553 ] = {
127
+ .name = "4553" ,
128
+ .id2_register = 0x32353534 ,
129
+ },
130
+ /* generic version with no id2_register at the end */
131
+ [TCAN4X5X ] = {
132
+ .name = "generic" ,
133
+ .has_wake_pin = true,
134
+ .has_state_pin = true,
135
+ },
136
+ };
137
+
106
138
static inline struct tcan4x5x_priv * cdev_to_priv (struct m_can_classdev * cdev )
107
139
{
108
140
return container_of (cdev , struct tcan4x5x_priv , cdev );
@@ -254,18 +286,53 @@ static int tcan4x5x_disable_state(struct m_can_classdev *cdev)
254
286
TCAN4X5X_DISABLE_INH_MSK , 0x01 );
255
287
}
256
288
257
- static int tcan4x5x_get_gpios (struct m_can_classdev * cdev )
289
+ static const struct tcan4x5x_version_info
290
+ * tcan4x5x_find_version (struct tcan4x5x_priv * priv )
291
+ {
292
+ u32 val ;
293
+ int ret ;
294
+
295
+ ret = regmap_read (priv -> regmap , TCAN4X5X_DEV_ID1 , & val );
296
+ if (ret )
297
+ return ERR_PTR (ret );
298
+
299
+ if (val != TCAN4X5X_DEV_ID1_TCAN ) {
300
+ dev_err (& priv -> spi -> dev , "Not a tcan device %x\n" , val );
301
+ return ERR_PTR (- ENODEV );
302
+ }
303
+
304
+ ret = regmap_read (priv -> regmap , TCAN4X5X_DEV_ID2 , & val );
305
+ if (ret )
306
+ return ERR_PTR (ret );
307
+
308
+ for (int i = 0 ; i != ARRAY_SIZE (tcan4x5x_versions ); ++ i ) {
309
+ const struct tcan4x5x_version_info * vinfo = & tcan4x5x_versions [i ];
310
+
311
+ if (!vinfo -> id2_register || val == vinfo -> id2_register ) {
312
+ dev_info (& priv -> spi -> dev , "Detected TCAN device version %s\n" ,
313
+ vinfo -> name );
314
+ return vinfo ;
315
+ }
316
+ }
317
+
318
+ return & tcan4x5x_versions [TCAN4X5X ];
319
+ }
320
+
321
+ static int tcan4x5x_get_gpios (struct m_can_classdev * cdev ,
322
+ const struct tcan4x5x_version_info * version_info )
258
323
{
259
324
struct tcan4x5x_priv * tcan4x5x = cdev_to_priv (cdev );
260
325
int ret ;
261
326
262
- tcan4x5x -> device_wake_gpio = devm_gpiod_get (cdev -> dev , "device-wake" ,
263
- GPIOD_OUT_HIGH );
264
- if (IS_ERR (tcan4x5x -> device_wake_gpio )) {
265
- if (PTR_ERR (tcan4x5x -> device_wake_gpio ) == - EPROBE_DEFER )
266
- return - EPROBE_DEFER ;
327
+ if (version_info -> has_wake_pin ) {
328
+ tcan4x5x -> device_wake_gpio = devm_gpiod_get (cdev -> dev , "device-wake" ,
329
+ GPIOD_OUT_HIGH );
330
+ if (IS_ERR (tcan4x5x -> device_wake_gpio )) {
331
+ if (PTR_ERR (tcan4x5x -> device_wake_gpio ) == - EPROBE_DEFER )
332
+ return - EPROBE_DEFER ;
267
333
268
- tcan4x5x_disable_wake (cdev );
334
+ tcan4x5x_disable_wake (cdev );
335
+ }
269
336
}
270
337
271
338
tcan4x5x -> reset_gpio = devm_gpiod_get_optional (cdev -> dev , "reset" ,
@@ -277,12 +344,14 @@ static int tcan4x5x_get_gpios(struct m_can_classdev *cdev)
277
344
if (ret )
278
345
return ret ;
279
346
280
- tcan4x5x -> device_state_gpio = devm_gpiod_get_optional (cdev -> dev ,
281
- "device-state" ,
282
- GPIOD_IN );
283
- if (IS_ERR (tcan4x5x -> device_state_gpio )) {
284
- tcan4x5x -> device_state_gpio = NULL ;
285
- tcan4x5x_disable_state (cdev );
347
+ if (version_info -> has_state_pin ) {
348
+ tcan4x5x -> device_state_gpio = devm_gpiod_get_optional (cdev -> dev ,
349
+ "device-state" ,
350
+ GPIOD_IN );
351
+ if (IS_ERR (tcan4x5x -> device_state_gpio )) {
352
+ tcan4x5x -> device_state_gpio = NULL ;
353
+ tcan4x5x_disable_state (cdev );
354
+ }
286
355
}
287
356
288
357
return 0 ;
@@ -299,6 +368,7 @@ static struct m_can_ops tcan4x5x_ops = {
299
368
300
369
static int tcan4x5x_can_probe (struct spi_device * spi )
301
370
{
371
+ const struct tcan4x5x_version_info * version_info ;
302
372
struct tcan4x5x_priv * priv ;
303
373
struct m_can_classdev * mcan_class ;
304
374
int freq , ret ;
@@ -361,7 +431,13 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
361
431
if (ret )
362
432
goto out_m_can_class_free_dev ;
363
433
364
- ret = tcan4x5x_get_gpios (mcan_class );
434
+ version_info = tcan4x5x_find_version (priv );
435
+ if (IS_ERR (version_info )) {
436
+ ret = PTR_ERR (version_info );
437
+ goto out_power ;
438
+ }
439
+
440
+ ret = tcan4x5x_get_gpios (mcan_class , version_info );
365
441
if (ret )
366
442
goto out_power ;
367
443
0 commit comments