1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
|
/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _LINUX_SLIMBUS_H
#define _LINUX_SLIMBUS_H
#include <linux/module.h>
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/mod_devicetable.h>
/* Interfaces between SLIMbus manager drivers and SLIMbus infrastructure. */
extern struct bus_type slimbus_type;
/* Standard values per SLIMbus spec needed by controllers and devices */
#define SLIM_CL_PER_SUPERFRAME 6144
#define SLIM_CL_PER_SUPERFRAME_DIV8 (SLIM_CL_PER_SUPERFRAME >> 3)
#define SLIM_MAX_TXNS 256
#define SLIM_MAX_CLK_GEAR 10
#define SLIM_MIN_CLK_GEAR 1
#define SLIM_CL_PER_SL 4
#define SLIM_SL_PER_SUPERFRAME (SLIM_CL_PER_SUPERFRAME >> 2)
#define SLIM_FRM_SLOTS_PER_SUPERFRAME 16
#define SLIM_GDE_SLOTS_PER_SUPERFRAME 2
/*
* SLIMbus message types. Related to interpretation of message code.
* Values are defined in Table 32 (slimbus spec 1.01.01)
*/
#define SLIM_MSG_MT_CORE 0x0
#define SLIM_MSG_MT_DEST_REFERRED_CLASS 0x1
#define SLIM_MSG_MT_DEST_REFERRED_USER 0x2
#define SLIM_MSG_MT_SRC_REFERRED_CLASS 0x5
#define SLIM_MSG_MT_SRC_REFERRED_USER 0x6
/*
* SLIMbus core type Message Codes.
* Values are defined in Table 65 (slimbus spec 1.01.01)
*/
/* Device management messages */
#define SLIM_MSG_MC_REPORT_PRESENT 0x1
#define SLIM_MSG_MC_ASSIGN_LOGICAL_ADDRESS 0x2
#define SLIM_MSG_MC_RESET_DEVICE 0x4
#define SLIM_MSG_MC_CHANGE_LOGICAL_ADDRESS 0x8
#define SLIM_MSG_MC_CHANGE_ARBITRATION_PRIORITY 0x9
#define SLIM_MSG_MC_REQUEST_SELF_ANNOUNCEMENT 0xC
#define SLIM_MSG_MC_REPORT_ABSENT 0xF
/* Data channel management messages */
#define SLIM_MSG_MC_CONNECT_SOURCE 0x10
#define SLIM_MSG_MC_CONNECT_SINK 0x11
#define SLIM_MSG_MC_DISCONNECT_PORT 0x14
#define SLIM_MSG_MC_CHANGE_CONTENT 0x18
/* Information management messages */
#define SLIM_MSG_MC_REQUEST_INFORMATION 0x20
#define SLIM_MSG_MC_REQUEST_CLEAR_INFORMATION 0x21
#define SLIM_MSG_MC_REPLY_INFORMATION 0x24
#define SLIM_MSG_MC_CLEAR_INFORMATION 0x28
#define SLIM_MSG_MC_REPORT_INFORMATION 0x29
/* Reconfiguration messages */
#define SLIM_MSG_MC_BEGIN_RECONFIGURATION 0x40
#define SLIM_MSG_MC_NEXT_ACTIVE_FRAMER 0x44
#define SLIM_MSG_MC_NEXT_SUBFRAME_MODE 0x45
#define SLIM_MSG_MC_NEXT_CLOCK_GEAR 0x46
#define SLIM_MSG_MC_NEXT_ROOT_FREQUENCY 0x47
#define SLIM_MSG_MC_NEXT_PAUSE_CLOCK 0x4A
#define SLIM_MSG_MC_NEXT_RESET_BUS 0x4B
#define SLIM_MSG_MC_NEXT_SHUTDOWN_BUS 0x4C
#define SLIM_MSG_MC_NEXT_DEFINE_CHANNEL 0x50
#define SLIM_MSG_MC_NEXT_DEFINE_CONTENT 0x51
#define SLIM_MSG_MC_NEXT_ACTIVATE_CHANNEL 0x54
#define SLIM_MSG_MC_NEXT_DEACTIVATE_CHANNEL 0x55
#define SLIM_MSG_MC_NEXT_REMOVE_CHANNEL 0x58
#define SLIM_MSG_MC_RECONFIGURE_NOW 0x5F
/*
* Clock pause flag to indicate that the reconfig message
* corresponds to clock pause sequence
*/
#define SLIM_MSG_CLK_PAUSE_SEQ_FLG (1U << 8)
/* Value management messages */
#define SLIM_MSG_MC_REQUEST_VALUE 0x60
#define SLIM_MSG_MC_REQUEST_CHANGE_VALUE 0x61
#define SLIM_MSG_MC_REPLY_VALUE 0x64
#define SLIM_MSG_MC_CHANGE_VALUE 0x68
/* Clock pause values defined in Table 66 (slimbus spec 1.01.01) */
#define SLIM_CLK_FAST 0
#define SLIM_CLK_CONST_PHASE 1
#define SLIM_CLK_UNSPECIFIED 2
struct slim_controller;
struct slim_device;
/* Destination type Values defined in Table 33 (slimbus spec 1.01.01) */
#define SLIM_MSG_DEST_LOGICALADDR 0
#define SLIM_MSG_DEST_ENUMADDR 1
#define SLIM_MSG_DEST_BROADCAST 3
/*
* @start_offset: Specifies starting offset in information/value element map
* @num_bytes: Can be 1, 2, 3, 4, 6, 8, 12, 16 per spec. This ensures that the
* message will fit in the 40-byte message limit and the slicesize can be
* compatible with values in table 21 (slimbus spec 1.01.01)
* @comp: Completion to indicate end of message-transfer. Used if client wishes
* to use the API asynchronously.
*/
struct slim_ele_access {
u16 start_offset;
u8 num_bytes;
struct completion *comp;
};
/*
* struct slim_framer - Represents Slimbus framer.
* Every controller may have multiple framers.
* Manager is responsible for framer hand-over.
* @e_addr: 6 byte Elemental address of the framer.
* @rootfreq: Root Frequency at which the framer can run. This is maximum
* frequency (clock gear 10 per slimbus spec) at which the bus can operate.
* @superfreq: Superframes per root frequency. Every frame is 6144 cells (bits)
* per slimbus specification.
*/
struct slim_framer {
u8 e_addr[6];
int rootfreq;
int superfreq;
};
#define to_slim_framer(d) container_of(d, struct slim_framer, dev);
/*
* struct slim_addrt: slimbus address used internally by the slimbus framework.
* @valid: If the device is still there or if the address can be reused.
* @eaddr: 6-bytes-long elemental address
* @laddr: It is possible that controller will set a predefined logical address
* rather than the one assigned by framework. (i.e. logical address may
* not be same as index into this table). This entry will store the
* logical address value for this enumeration address.
*/
struct slim_addrt {
bool valid;
u8 eaddr[6];
u8 laddr;
};
/*
* struct slim_val_inf: slimbus value/information element transaction
* @start_offset: Specifies starting offset in information/value element map
* @num_bytes: number of bytes to be read/written
* @wbuf: buffer if this transaction has 'write' component in it
* @rbuf: buffer if this transaction has 'read' component in it
*/
struct slim_val_inf {
u16 start_offset;
u8 num_bytes;
u8 *wbuf;
u8 *rbuf;
};
/*
* struct slim_msg_txn: Message to be sent by the controller.
* Linux framework uses this structure with drivers implementing controller.
* This structure has packet header, payload and buffer to be filled (if any)
* For the header information, refer to Table 34-36.
* @rl: Header field. remaining length.
* @mt: Header field. Message type.
* @mc: Header field. LSB is message code for type mt. Framework will set MSB to
* SLIM_MSG_CLK_PAUSE_SEQ_FLG in case "mc" in the reconfiguration sequence
* is for pausing the clock.
* @dt: Header field. Destination type.
* @ec: Element size. Used for elemental access APIs.
* @len: Length of payload. (excludes ec)
* @tid: Transaction ID. Used for messages expecting response.
* (e.g. relevant for mc = SLIM_MSG_MC_REQUEST_INFORMATION)
* @la: Logical address of the device this message is going to.
* (Not used when destination type is broadcast.)
* @async: If this transaction is async
* @rbuf: Buffer to be populated by controller when response is received.
* @wbuf: Payload of the message. (e.g. channel number for DATA channel APIs)
* @comp: Completion structure. Used by controller to notify response.
* (Field is relevant when tid is used)
*/
struct slim_msg_txn {
u8 rl;
u8 mt;
u16 mc;
u8 dt;
u16 ec;
u8 len;
u8 tid;
u8 la;
bool async;
u8 *rbuf;
const u8 *wbuf;
struct completion *comp;
};
/* Internal port state used by slimbus framework to manage data-ports */
enum slim_port_state {
SLIM_P_FREE,
SLIM_P_UNCFG,
SLIM_P_CFG,
};
/*
* enum slim_port_req: Request port type by user through APIs to manage ports
* User can request default, half-duplex or port to be used in multi-channel
* configuration. Default indicates a simplex port.
*/
enum slim_port_req {
SLIM_REQ_DEFAULT,
SLIM_REQ_HALF_DUP,
SLIM_REQ_MULTI_CH,
};
/*
* enum slim_port_opts: Port options requested.
* User can request no configuration, packed data, and/or MSB aligned data port
*/
enum slim_port_opts {
SLIM_OPT_NONE = 0,
SLIM_OPT_NO_PACK = 1U,
SLIM_OPT_ALIGN_MSB = 1U << 1,
};
/* enum slim_port_flow: Port flow type (inbound/outbound). */
enum slim_port_flow {
SLIM_SRC,
SLIM_SINK,
};
/* enum slim_port_err: Port errors */
enum slim_port_err {
SLIM_P_INPROGRESS,
SLIM_P_OVERFLOW,
SLIM_P_UNDERFLOW,
SLIM_P_DISCONNECT,
SLIM_P_NOT_OWNED,
};
/*
* struct slim_port_cfg: Port config for the manager port
* port_opts: port options (bit-map) for this port
* watermark: watermark level set for this port
*/
struct slim_port_cfg {
u32 port_opts;
u32 watermark;
};
/*
* struct slim_port: Internal structure used by framework to manage ports
* @err: Port error if any for this port. Refer to enum above.
* @state: Port state. Refer to enum above.
* @req: Port request for this port.
* @cfg: Port configuration for this port.
* @flow: Flow type of this port.
* @ch: Channel association of this port.
* @xcomp: Completion to indicate error, data transfer done event.
* @ctrl: Controller to which this port belongs to. This is useful to associate
* port with the SW since port hardware interrupts may only contain port
* information.
*/
struct slim_port {
enum slim_port_err err;
enum slim_port_state state;
enum slim_port_req req;
struct slim_port_cfg cfg;
enum slim_port_flow flow;
struct slim_ch *ch;
struct completion *xcomp;
struct slim_controller *ctrl;
};
/*
* enum slim_ch_state: Channel state of a channel.
* Channel transition happens from free-to-allocated-to-defined-to-pending-
* active-to-active.
* Once active, channel can be removed or suspended. Suspended channels are
* still scheduled, but data transfer doesn't happen.
* Removed channels are not deallocated until dealloc_ch API is used.
* Deallocation reset channel state back to free.
* Removed channels can be defined with different parameters.
*/
enum slim_ch_state {
SLIM_CH_FREE,
SLIM_CH_ALLOCATED,
SLIM_CH_DEFINED,
SLIM_CH_PENDING_ACTIVE,
SLIM_CH_ACTIVE,
SLIM_CH_SUSPENDED,
SLIM_CH_PENDING_REMOVAL,
};
/*
* enum slim_ch_proto: Channel protocol used by the channel.
* Hard Isochronous channel is not scheduled if current frequency doesn't allow
* the channel to be run without flow-control.
* Auto isochronous channel will be scheduled as hard-isochronous or push-pull
* depending on current bus frequency.
* Currently, Push-pull or async or extended channels are not supported.
* For more details, refer to slimbus spec
*/
enum slim_ch_proto {
SLIM_HARD_ISO,
SLIM_AUTO_ISO,
SLIM_PUSH,
SLIM_PULL,
SLIM_ASYNC_SMPLX,
SLIM_ASYNC_HALF_DUP,
SLIM_EXT_SMPLX,
SLIM_EXT_HALF_DUP,
};
/*
* enum slim_ch_rate: Most commonly used frequency rate families.
* Use 1HZ for push-pull transport.
* 4KHz and 11.025KHz are most commonly used in audio applications.
* Typically, slimbus runs at frequencies to support channels running at 4KHz
* and/or 11.025KHz isochronously.
*/
enum slim_ch_rate {
SLIM_RATE_1HZ,
SLIM_RATE_4000HZ,
SLIM_RATE_11025HZ,
};
/*
* enum slim_ch_coeff: Coefficient of a channel used internally by framework.
* Coefficient is applicable to channels running isochronously.
* Coefficient is calculated based on channel rate multiplier.
* (If rate multiplier is power of 2, it's coeff.1 channel. Otherwise it's
* coeff.3 channel.
*/
enum slim_ch_coeff {
SLIM_COEFF_1,
SLIM_COEFF_3,
};
/*
* enum slim_ch_control: Channel control.
* Activate will schedule channel and/or group of channels in the TDM frame.
* Suspend will keep the schedule but data-transfer won't happen.
* Remove will remove the channel/group from the TDM frame.
*/
enum slim_ch_control {
SLIM_CH_ACTIVATE,
SLIM_CH_SUSPEND,
SLIM_CH_REMOVE,
};
/* enum slim_ch_dataf: Data format per table 60 from slimbus spec 1.01.01 */
enum slim_ch_dataf {
SLIM_CH_DATAF_NOT_DEFINED = 0,
SLIM_CH_DATAF_LPCM_AUDIO = 1,
SLIM_CH_DATAF_IEC61937_COMP_AUDIO = 2,
SLIM_CH_DATAF_PACKED_PDM_AUDIO = 3,
};
/* enum slim_ch_auxf: Auxiliary field format per table 59 from slimbus spec */
enum slim_ch_auxf {
SLIM_CH_AUXF_NOT_APPLICABLE = 0,
SLIM_CH_AUXF_ZCUV_TUNNEL_IEC60958 = 1,
SLIM_CH_USER_DEFINED = 0xF,
};
/*
* struct slim_ch: Channel structure used externally by users of channel APIs.
* @prot: Desired slimbus protocol.
* @baser: Desired base rate. (Typical isochronous rates are: 4KHz, or 11.025KHz
* @dataf: Data format.
* @auxf: Auxiliary format.
* @ratem: Channel rate multiplier. (e.g. 48KHz channel will have 4KHz base rate
* and 12 as rate multiplier.
* @sampleszbits: Sample size in bits.
*/
struct slim_ch {
enum slim_ch_proto prot;
enum slim_ch_rate baser;
enum slim_ch_dataf dataf;
enum slim_ch_auxf auxf;
u32 ratem;
u32 sampleszbits;
};
/*
* struct slim_ich: Internal channel structure used by slimbus framework.
* @prop: structure passed by the client.
* @coeff: Coefficient of this channel.
* @state: Current state of the channel.
* @nextgrp: If this channel is part of group, next channel in this group.
* @prrate: Presence rate of this channel (per table 62 of the spec)
* @offset: Offset of this channel in the superframe.
* @newoff: Used during scheduling to hold temporary new offset until the offset
* is accepted/rejected by slimbus reconfiguration.
* @interval: Interval of this channel per superframe.
* @newintr: Used during scheduling to new interval temporarily.
* @seglen: Segment length of this channel.
* @rootexp: root exponent of this channel. Rate can be found using rootexp and
* coefficient. Used during scheduling.
* @srch: Source port used by this channel.
* @sinkh: Sink ports used by this channel.
* @nsink: number of sink ports used by this channel.
* @chan: Channel number sent on hardware lines for this channel. May not be
* equal to array-index into chans if client requested to use number beyond
* channel-array for the controller.
* @ref: Reference number to keep track of how many clients (upto 2) are using
* this channel.
* @def: Used to keep track of how many times the channel definition is sent
* to hardware and this will decide if channel-remove can be sent for the
* channel. Channel definition may be sent upto twice (once per producer
* and once per consumer). Channel removal should be sent only once to
* avoid clients getting underflow/overflow errors.
*/
struct slim_ich {
struct slim_ch prop;
enum slim_ch_coeff coeff;
enum slim_ch_state state;
u16 nextgrp;
u32 prrate;
u32 offset;
u32 newoff;
u32 interval;
u32 newintr;
u32 seglen;
u8 rootexp;
u32 srch;
u32 *sinkh;
int nsink;
u8 chan;
int ref;
int def;
};
/*
* struct slim_sched: Framework uses this structure internally for scheduling.
* @chc3: Array of all active coeffient 3 channels.
* @num_cc3: Number of active coeffient 3 channels.
* @chc1: Array of all active coeffient 1 channels.
* @num_cc1: Number of active coeffient 1 channels.
* @subfrmcode: Current subframe-code used by TDM. This is decided based on
* requested message bandwidth and current channels scheduled.
* @usedslots: Slots used by all active channels.
* @msgsl: Slots used by message-bandwidth.
* @pending_msgsl: Used to store pending request of message bandwidth (in slots)
* until the scheduling is accepted by reconfiguration.
* @m_reconf: This mutex is held until current reconfiguration (data channel
* scheduling, message bandwidth reservation) is done. Message APIs can
* use the bus concurrently when this mutex is held since elemental access
* messages can be sent on the bus when reconfiguration is in progress.
* @slots: Used for debugging purposes to debug/verify current schedule in TDM.
*/
struct slim_sched {
struct slim_ich **chc3;
int num_cc3;
struct slim_ich **chc1;
int num_cc1;
u32 subfrmcode;
u32 usedslots;
u32 msgsl;
u32 pending_msgsl;
struct mutex m_reconf;
u8 *slots;
};
/*
* enum slim_clk_state: Slimbus controller's clock state used internally for
* maintaining current clock state.
* @SLIM_CLK_ACTIVE: Slimbus clock is active
* @SLIM_CLK_PAUSE_FAILED: Slimbus controlled failed to go in clock pause.
* Hardware-wise, this state is same as active but controller will wait on
* completion before making transition to SLIM_CLK_ACTIVE in framework
* @SLIM_CLK_ENTERING_PAUSE: Slimbus clock pause sequence is being sent on the
* bus. If this succeeds, state changes to SLIM_CLK_PAUSED. If the
* transition fails, state changes to SLIM_CLK_PAUSE_FAILED
* @SLIM_CLK_PAUSED: Slimbus controller clock has paused.
*/
enum slim_clk_state {
SLIM_CLK_ACTIVE,
SLIM_CLK_ENTERING_PAUSE,
SLIM_CLK_PAUSE_FAILED,
SLIM_CLK_PAUSED,
};
/*
* struct slim_controller: Represents manager for a SlimBUS
* (similar to 'master' on I2C)
* @dev: Device interface to this driver
* @nr: Board-specific number identifier for this controller/bus
* @list: Link with other slimbus controllers
* @name: Name for this controller
* @clkgear: Current clock gear in which this bus is running
* @min_cg: Minimum clock gear supported by this controller (default value: 1)
* @max_cg: Maximum clock gear supported by this controller (default value: 10)
* @clk_state: Controller's clock state from enum slim_clk_state
* @pause_comp: Signals completion of clock pause sequence. This is useful when
* client tries to call slimbus transaction when controller may be entering
* clock pause.
* @a_framer: Active framer which is clocking the bus managed by this controller
* @m_ctrl: Mutex protecting controller data structures (ports, channels etc)
* @addrt: Logical address table
* @num_dev: Number of active slimbus slaves on this bus
* @devs: List of devices on this controller
* @wq: Workqueue per controller used to notify devices when they report present
* @txnt: Table of transactions having transaction ID
* @last_tid: size of the table txnt (can't grow beyond 256 since TID is 8-bits)
* @ports: Ports associated with this controller
* @nports: Number of ports supported by the controller
* @chans: Channels associated with this controller
* @nchans: Number of channels supported
* @reserved: Reserved channels that controller wants to use internally
* Clients will be assigned channel numbers after this number
* @sched: scheduler structure used by the controller
* @dev_released: completion used to signal when sysfs has released this
* controller so that it can be deleted during shutdown
* @xfer_msg: Transfer a message on this controller (this can be a broadcast
* control/status message like data channel setup, or a unicast message
* like value element read/write.
* @set_laddr: Setup logical address at laddr for the slave with elemental
* address e_addr. Drivers implementing controller will be expected to
* send unicast message to this device with its logical address.
* @allocbw: Controller can override default reconfiguration and channel
* scheduling algorithm.
* @get_laddr: It is possible that controller needs to set fixed logical
* address table and get_laddr can be used in that case so that controller
* can do this assignment.
* @wakeup: This function pointer implements controller-specific procedure
* to wake it up from clock-pause. Framework will call this to bring
* the controller out of clock pause.
* @alloc_port: Allocate a port and make it ready for data transfer. This is
* called by framework to make sure controller can take necessary steps
* to initialize its port
* @dealloc_port: Counter-part of alloc_port. This is called by framework so
* that controller can free resources associated with this port
* @framer_handover: If this controller has multiple framers, this API will
* be called to switch between framers if controller desires to change
* the active framer.
* @port_xfer: Called to schedule a transfer on port pn. iobuf is physical
* address and the buffer may have to be DMA friendly since data channels
* will be using data from this buffers without SW intervention.
* @port_xfer_status: Called by framework when client calls get_xfer_status
* API. Returns how much buffer is actually processed and the port
* errors (e.g. overflow/underflow) if any.
* @xfer_user_msg: Send user message to specified logical address. Underlying
* controller has to support sending user messages. Returns error if any.
* @xfer_bulk_wr: Send bulk of write messages to specified logical address.
* Underlying controller has to support this. Typically useful to transfer
* messages to download firmware, or messages where strict ordering for
* slave is necessary
*/
struct slim_controller {
struct device dev;
unsigned int nr;
struct list_head list;
char name[SLIMBUS_NAME_SIZE];
int clkgear;
int min_cg;
int max_cg;
enum slim_clk_state clk_state;
struct completion pause_comp;
struct slim_framer *a_framer;
struct mutex m_ctrl;
struct slim_addrt *addrt;
u8 num_dev;
struct list_head devs;
struct workqueue_struct *wq;
struct slim_msg_txn *txnt[SLIM_MAX_TXNS];
u8 last_tid;
spinlock_t txn_lock;
struct slim_port *ports;
int nports;
struct slim_ich *chans;
int nchans;
u8 reserved;
struct slim_sched sched;
struct completion dev_released;
int (*xfer_msg)(struct slim_controller *ctrl,
struct slim_msg_txn *txn);
int (*set_laddr)(struct slim_controller *ctrl,
const u8 *ea, u8 elen, u8 laddr);
int (*allocbw)(struct slim_device *sb,
int *subfrmc, int *clkgear);
int (*get_laddr)(struct slim_controller *ctrl,
const u8 *ea, u8 elen, u8 *laddr);
int (*wakeup)(struct slim_controller *ctrl);
int (*alloc_port)(struct slim_controller *ctrl,
u8 port);
void (*dealloc_port)(struct slim_controller *ctrl,
u8 port);
int (*framer_handover)(struct slim_controller *ctrl,
struct slim_framer *new_framer);
int (*port_xfer)(struct slim_controller *ctrl,
u8 pn, phys_addr_t iobuf, u32 len,
struct completion *comp);
enum slim_port_err (*port_xfer_status)(struct slim_controller *ctr,
u8 pn, phys_addr_t *done_buf, u32 *done_len);
int (*xfer_user_msg)(struct slim_controller *ctrl,
u8 la, u8 mt, u8 mc,
struct slim_ele_access *msg, u8 *buf, u8 len);
int (*xfer_bulk_wr)(struct slim_controller *ctrl,
u8 la, u8 mt, u8 mc, struct slim_val_inf msgs[],
int n, int (*comp_cb)(void *ctx, int err),
void *ctx);
};
#define to_slim_controller(d) container_of(d, struct slim_controller, dev)
/*
* struct slim_driver: Manage Slimbus generic/slave device driver
* @probe: Binds this driver to a slimbus device.
* @remove: Unbinds this driver from the slimbus device.
* @shutdown: Standard shutdown callback used during powerdown/halt.
* @suspend: Standard suspend callback used during system suspend
* @resume: Standard resume callback used during system resume
* @device_up: This callback is called when the device reports present and
* gets a logical address assigned to it
* @device_down: This callback is called when device reports absent, or the
* bus goes down. Device will report present when bus is up and
* device_up callback will be called again when that happens
* @reset_device: This callback is called after framer is booted.
* Driver should do the needful to reset the device,
* so that device acquires sync and be operational.
* @driver: Slimbus device drivers should initialize name and owner field of
* this structure
* @id_table: List of slimbus devices supported by this driver
*/
struct slim_driver {
int (*probe)(struct slim_device *sldev);
int (*remove)(struct slim_device *sldev);
void (*shutdown)(struct slim_device *sldev);
int (*suspend)(struct slim_device *sldev,
pm_message_t pmesg);
int (*resume)(struct slim_device *sldev);
int (*device_up)(struct slim_device *sldev);
int (*device_down)
(struct slim_device *sldev);
int (*reset_device)
(struct slim_device *sldev);
struct device_driver driver;
const struct slim_device_id *id_table;
};
#define to_slim_driver(d) container_of(d, struct slim_driver, driver)
/*
* struct slim_pending_ch: List of pending channels used by framework.
* @chan: Channel number
* @pending: list of channels
*/
struct slim_pending_ch {
u8 chan;
struct list_head pending;
};
/*
* Client/device handle (struct slim_device):
* ------------------------------------------
* This is the client/device handle returned when a slimbus
* device is registered with a controller. This structure can be provided
* during register_board_info, or can be allocated using slim_add_device API.
* Pointer to this structure is used by client-driver as a handle.
* @dev: Driver model representation of the device.
* @name: Name of driver to use with this device.
* @e_addr: 6-byte elemental address of this device.
* @driver: Device's driver. Pointer to access routines.
* @ctrl: Slimbus controller managing the bus hosting this device.
* @laddr: 1-byte Logical address of this device.
* @reported: Flag to indicate whether this device reported present. The flag
* is set when device reports present, and is reset when it reports
* absent. This flag alongwith notified flag below is used to call
* device_up, or device_down callbacks for driver of this device.
* @mark_define: List of channels pending definition/activation.
* @mark_suspend: List of channels pending suspend.
* @mark_removal: List of channels pending removal.
* @notified: Flag to indicate whether this device has been notified. The
* device may report present multiple times, but should be notified only
* first time it has reported present.
* @dev_list: List of devices on a controller
* @wd: Work structure associated with workqueue for presence notification
* @sldev_reconf: Mutex to protect the pending data-channel lists.
* @pending_msgsl: Message bandwidth reservation request by this client in
* slots that's pending reconfiguration.
* @cur_msgsl: Message bandwidth reserved by this client in slots.
* These 3 lists are managed by framework. Lists are populated when client
* calls channel control API without reconfig-flag set and the lists are
* emptied when the reconfiguration is done by this client.
*/
struct slim_device {
struct device dev;
const char *name;
u8 e_addr[6];
struct slim_driver *driver;
struct slim_controller *ctrl;
u8 laddr;
bool reported;
struct list_head mark_define;
struct list_head mark_suspend;
struct list_head mark_removal;
bool notified;
struct list_head dev_list;
struct work_struct wd;
struct mutex sldev_reconf;
u32 pending_msgsl;
u32 cur_msgsl;
};
#define to_slim_device(d) container_of(d, struct slim_device, dev)
/*
* struct slim_boardinfo: Declare board info for Slimbus device bringup.
* @bus_num: Controller number (bus) on which this device will sit.
* @slim_slave: Device to be registered with slimbus.
*/
struct slim_boardinfo {
int bus_num;
struct slim_device *slim_slave;
};
/*
* slim_get_logical_addr: Return the logical address of a slimbus device.
* @sb: client handle requesting the adddress.
* @e_addr: Elemental address of the device.
* @e_len: Length of e_addr
* @laddr: output buffer to store the address
* context: can sleep
* -EINVAL is returned in case of invalid parameters, and -ENXIO is returned if
* the device with this elemental address is not found.
*/
extern int slim_get_logical_addr(struct slim_device *sb, const u8 *e_addr,
u8 e_len, u8 *laddr);
/* Message APIs Unicast message APIs used by slimbus slave drivers */
/*
* Message API access routines.
* @sb: client handle requesting elemental message reads, writes.
* @msg: Input structure for start-offset, number of bytes to read.
* @rbuf: data buffer to be filled with values read.
* @len: data buffer size
* @wbuf: data buffer containing value/information to be written
* context: can sleep
* Returns:
* -EINVAL: Invalid parameters
* -ETIMEDOUT: If controller could not complete the request. This may happen if
* the bus lines are not clocked, controller is not powered-on, slave with
* given address is not enumerated/responding.
*/
extern int slim_request_val_element(struct slim_device *sb,
struct slim_ele_access *msg, u8 *buf,
u8 len);
extern int slim_request_inf_element(struct slim_device *sb,
struct slim_ele_access *msg, u8 *buf,
u8 len);
extern int slim_change_val_element(struct slim_device *sb,
struct slim_ele_access *msg,
const u8 *buf, u8 len);
extern int slim_clear_inf_element(struct slim_device *sb,
struct slim_ele_access *msg, u8 *buf,
u8 len);
extern int slim_request_change_val_element(struct slim_device *sb,
struct slim_ele_access *msg, u8 *rbuf,
const u8 *wbuf, u8 len);
extern int slim_request_clear_inf_element(struct slim_device *sb,
struct slim_ele_access *msg, u8 *rbuf,
const u8 *wbuf, u8 len);
/*
* Broadcast message API:
* call this API directly with sbdev = NULL.
* For broadcast reads, make sure that buffers are big-enough to incorporate
* replies from all logical addresses.
* All controllers may not support broadcast
*/
extern int slim_xfer_msg(struct slim_controller *ctrl,
struct slim_device *sbdev, struct slim_ele_access *msg,
u16 mc, u8 *rbuf, const u8 *wbuf, u8 len);
/*
* User message:
* slim_user_msg: Send user message that is interpreted by destination device
* @sb: Client handle sending the message
* @la: Destination device for this user message
* @mt: Message Type (Soruce-referred, or Destination-referred)
* @mc: Message Code
* @msg: Message structure (start offset, number of bytes) to be sent
* @buf: data buffer to be sent
* @len: data buffer size in bytes
*/
extern int slim_user_msg(struct slim_device *sb, u8 la, u8 mt, u8 mc,
struct slim_ele_access *msg, u8 *buf, u8 len);
/*
* Queue bulk of message writes:
* slim_bulk_msg_write: Write bulk of messages (e.g. downloading FW)
* @sb: Client handle sending these messages
* @la: Destination device for these messages
* @mt: Message Type
* @mc: Message Code
* @msgs: List of messages to be written in bulk
* @n: Number of messages in the list
* @cb: Callback if client needs this to be non-blocking
* @ctx: Context for this callback
* If supported by controller, this message list will be sent in bulk to the HW
* If the client specifies this to be non-blocking, the callback will be
* called from atomic context.
*/
extern int slim_bulk_msg_write(struct slim_device *sb, u8 mt, u8 mc,
struct slim_val_inf msgs[], int n,
int (*comp_cb)(void *ctx, int err), void *ctx);
/* end of message apis */
/* Port management for manager device APIs */
/*
* slim_alloc_mgrports: Allocate port on manager side.
* @sb: device/client handle.
* @req: Port request type.
* @nports: Number of ports requested
* @rh: output buffer to store the port handles
* @hsz: size of buffer storing handles
* context: can sleep
* This port will be typically used by SW. e.g. client driver wants to receive
* some data from audio codec HW using a data channel.
* Port allocated using this API will be used to receive the data.
* If half-duplex ports are requested, two adjacent ports are allocated for
* 1 half-duplex port. So the handle-buffer size should be twice the number
* of half-duplex ports to be allocated.
* -EDQUOT is returned if all ports are in use.
*/
extern int slim_alloc_mgrports(struct slim_device *sb, enum slim_port_req req,
int nports, u32 *rh, int hsz);
/* Deallocate the port(s) allocated using the API above */
extern int slim_dealloc_mgrports(struct slim_device *sb, u32 *hdl, int hsz);
/*
* slim_config_mgrports: Configure manager side ports
* @sb: device/client handle.
* @ph: array of port handles for which this configuration is valid
* @nports: Number of ports in ph
* @cfg: configuration requested for port(s)
* Configure port settings if they are different than the default ones.
* Returns success if the config could be applied. Returns -EISCONN if the
* port is in use
*/
extern int slim_config_mgrports(struct slim_device *sb, u32 *ph, int nports,
struct slim_port_cfg *cfg);
/*
* slim_port_xfer: Schedule buffer to be transferred/received using port-handle.
* @sb: client handle
* @ph: port-handle
* @iobuf: buffer to be transferred or populated
* @len: buffer size.
* @comp: completion signal to indicate transfer done or error.
* context: can sleep
* Returns number of bytes transferred/received if used synchronously.
* Will return 0 if used asynchronously.
* Client will call slim_port_get_xfer_status to get error and/or number of
* bytes transferred if used asynchronously.
*/
extern int slim_port_xfer(struct slim_device *sb, u32 ph, phys_addr_t iobuf,
u32 len, struct completion *comp);
/*
* slim_port_get_xfer_status: Poll for port transfers, or get transfer status
* after completion is done.
* @sb: client handle
* @ph: port-handle
* @done_buf: return pointer (iobuf from slim_port_xfer) which is processed.
* @done_len: Number of bytes transferred.
* This can be called when port_xfer complition is signalled.
* The API will return port transfer error (underflow/overflow/disconnect)
* and/or done_len will reflect number of bytes transferred. Note that
* done_len may be valid even if port error (overflow/underflow) has happened.
* e.g. If the transfer was scheduled with a few bytes to be transferred and
* client has not supplied more data to be transferred, done_len will indicate
* number of bytes transferred with underflow error. To avoid frequent underflow
* errors, multiple transfers can be queued (e.g. ping-pong buffers) so that
* channel has data to be transferred even if client is not ready to transfer
* data all the time. done_buf will indicate address of the last buffer
* processed from the multiple transfers.
*/
extern enum slim_port_err slim_port_get_xfer_status(struct slim_device *sb,
u32 ph, phys_addr_t *done_buf, u32 *done_len);
/*
* slim_connect_src: Connect source port to channel.
* @sb: client handle
* @srch: source handle to be connected to this channel
* @chanh: Channel with which the ports need to be associated with.
* Per slimbus specification, a channel may have 1 source port.
* Channel specified in chanh needs to be allocated first.
* Returns -EALREADY if source is already configured for this channel.
* Returns -ENOTCONN if channel is not allocated
* Returns -EINVAL if invalid direction is specified for non-manager port,
* or if the manager side port number is out of bounds, or in incorrect state
*/
extern int slim_connect_src(struct slim_device *sb, u32 srch, u16 chanh);
/*
* slim_connect_sink: Connect sink port(s) to channel.
* @sb: client handle
* @sinkh: sink handle(s) to be connected to this channel
* @nsink: number of sinks
* @chanh: Channel with which the ports need to be associated with.
* Per slimbus specification, a channel may have multiple sink-ports.
* Channel specified in chanh needs to be allocated first.
* Returns -EALREADY if sink is already configured for this channel.
* Returns -ENOTCONN if channel is not allocated
* Returns -EINVAL if invalid parameters are passed, or invalid direction is
* specified for non-manager port, or if the manager side port number is out of
* bounds, or in incorrect state
*/
extern int slim_connect_sink(struct slim_device *sb, u32 *sinkh, int nsink,
u16 chanh);
/*
* slim_disconnect_ports: Disconnect port(s) from channel
* @sb: client handle
* @ph: ports to be disconnected
* @nph: number of ports.
* Disconnects ports from a channel.
*/
extern int slim_disconnect_ports(struct slim_device *sb, u32 *ph, int nph);
/*
* slim_get_slaveport: Get slave port handle
* @la: slave device logical address.
* @idx: port index at slave
* @rh: return handle
* @flw: Flow type (source or destination)
* This API only returns a slave port's representation as expected by slimbus
* driver. This port is not managed by the slimbus driver. Caller is expected
* to have visibility of this port since it's a device-port.
*/
extern int slim_get_slaveport(u8 la, int idx, u32 *rh, enum slim_port_flow flw);
/* Channel functions. */
/*
* slim_alloc_ch: Allocate a slimbus channel and return its handle.
* @sb: client handle.
* @chanh: return channel handle
* Slimbus channels are limited to 256 per specification.
* -EXFULL is returned if all channels are in use.
* Although slimbus specification supports 256 channels, a controller may not
* support that many channels.
*/
extern int slim_alloc_ch(struct slim_device *sb, u16 *chanh);
/*
* slim_query_ch: Get reference-counted handle for a channel number. Every
* channel is reference counted by one as producer and the others as
* consumer)
* @sb: client handle
* @chan: slimbus channel number
* @chanh: return channel handle
* If request channel number is not in use, it is allocated, and reference
* count is set to one. If the channel was was already allocated, this API
* will return handle to that channel and reference count is incremented.
* -EXFULL is returned if all channels are in use
*/
extern int slim_query_ch(struct slim_device *sb, u8 chan, u16 *chanh);
/*
* slim_dealloc_ch: Deallocate channel allocated using the API above
* -EISCONN is returned if the channel is tried to be deallocated without
* being removed first.
* -ENOTCONN is returned if deallocation is tried on a channel that's not
* allocated.
*/
extern int slim_dealloc_ch(struct slim_device *sb, u16 chanh);
/*
* slim_define_ch: Define a channel.This API defines channel parameters for a
* given channel.
* @sb: client handle.
* @prop: slim_ch structure with channel parameters desired to be used.
* @chanh: list of channels to be defined.
* @nchan: number of channels in a group (1 if grp is false)
* @grp: Are the channels grouped
* @grph: return group handle if grouping of channels is desired.
* Channels can be grouped if multiple channels use same parameters
* (e.g. 5.1 audio has 6 channels with same parameters. They will all be
* grouped and given 1 handle for simplicity and avoid repeatedly calling
* the API)
* -EISCONN is returned if channel is already used with different parameters.
* -ENXIO is returned if the channel is not yet allocated.
*/
extern int slim_define_ch(struct slim_device *sb, struct slim_ch *prop,
u16 *chanh, u8 nchan, bool grp, u16 *grph);
/*
* slim_control_ch: Channel control API.
* @sb: client handle
* @grpchanh: group or channel handle to be controlled
* @chctrl: Control command (activate/suspend/remove)
* @commit: flag to indicate whether the control should take effect right-away.
* This API activates, removes or suspends a channel (or group of channels)
* grpchanh indicates the channel or group handle (returned by the define_ch
* API). Reconfiguration may be time-consuming since it can change all other
* active channel allocations on the bus, change in clock gear used by the
* slimbus, and change in the control space width used for messaging.
* commit makes sure that multiple channels can be activated/deactivated before
* reconfiguration is started.
* -EXFULL is returned if there is no space in TDM to reserve the bandwidth.
* -EISCONN/-ENOTCONN is returned if the channel is already connected or not
* yet defined.
* -EINVAL is returned if individual control of a grouped-channel is attempted.
*/
extern int slim_control_ch(struct slim_device *sb, u16 grpchanh,
enum slim_ch_control chctrl, bool commit);
/*
* slim_get_ch_state: Channel state.
* This API returns the channel's state (active, suspended, inactive etc)
*/
extern enum slim_ch_state slim_get_ch_state(struct slim_device *sb,
u16 chanh);
/*
* slim_reservemsg_bw: Request to reserve bandwidth for messages.
* @sb: client handle
* @bw_bps: message bandwidth in bits per second to be requested
* @commit: indicates whether the reconfiguration needs to be acted upon.
* This API call can be grouped with slim_control_ch API call with only one of
* the APIs specifying the commit flag to avoid reconfiguration being called too
* frequently. -EXFULL is returned if there is no space in TDM to reserve the
* bandwidth. -EBUSY is returned if reconfiguration is requested, but a request
* is already in progress.
*/
extern int slim_reservemsg_bw(struct slim_device *sb, u32 bw_bps, bool commit);
/*
* slim_reconfigure_now: Request reconfiguration now.
* @sb: client handle
* This API does what commit flag in other scheduling APIs do.
* -EXFULL is returned if there is no space in TDM to reserve the
* bandwidth. -EBUSY is returned if reconfiguration request is already in
* progress.
*/
extern int slim_reconfigure_now(struct slim_device *sb);
/*
* slim_ctrl_clk_pause: Called by slimbus controller to request clock to be
* paused or woken up out of clock pause
* @ctrl: controller requesting bus to be paused or woken up
* @wakeup: Wakeup this controller from clock pause.
* @restart: Restart time value per spec used for clock pause. This value
* isn't used when controller is to be woken up.
* This API executes clock pause reconfiguration sequence if wakeup is false.
* If wakeup is true, controller's wakeup is called
* Slimbus clock is idle and can be disabled by the controller later.
*/
extern int slim_ctrl_clk_pause(struct slim_controller *ctrl, bool wakeup,
u8 restart);
/*
* slim_driver_register: Client driver registration with slimbus
* @drv:Client driver to be associated with client-device.
* This API will register the client driver with the slimbus
* It is called from the driver's module-init function.
*/
extern int slim_driver_register(struct slim_driver *drv);
/*
* slim_driver_unregister: Undo effects of slim_driver_register
* @drv: Client driver to be unregistered
*/
extern void slim_driver_unregister(struct slim_driver *drv);
/*
* slim_add_numbered_controller: Controller bring-up.
* @ctrl: Controller to be registered.
* A controller is registered with the framework using this API. ctrl->nr is the
* desired number with which slimbus framework registers the controller.
* Function will return -EBUSY if the number is in use.
*/
extern int slim_add_numbered_controller(struct slim_controller *ctrl);
/*
* slim_del_controller: Controller tear-down.
* Controller added with the above API is teared down using this API.
*/
extern int slim_del_controller(struct slim_controller *ctrl);
/*
* slim_add_device: Add a new device without register board info.
* @ctrl: Controller to which this device is to be added to.
* Called when device doesn't have an explicit client-driver to be probed, or
* the client-driver is a module installed dynamically.
*/
extern int slim_add_device(struct slim_controller *ctrl,
struct slim_device *sbdev);
/* slim_remove_device: Remove the effect of slim_add_device() */
extern void slim_remove_device(struct slim_device *sbdev);
/*
* slim_assign_laddr: Assign logical address to a device enumerated.
* @ctrl: Controller with which device is enumerated.
* @e_addr: 6-byte elemental address of the device.
* @e_len: buffer length for e_addr
* @laddr: Return logical address (if valid flag is false)
* @valid: true if laddr holds a valid address that controller wants to
* set for this enumeration address. Otherwise framework sets index into
* address table as logical address.
* Called by controller in response to REPORT_PRESENT. Framework will assign
* a logical address to this enumeration address.
* Function returns -EXFULL to indicate that all logical addresses are already
* taken.
*/
extern int slim_assign_laddr(struct slim_controller *ctrl, const u8 *e_addr,
u8 e_len, u8 *laddr, bool valid);
/*
* slim_report_absent: Controller calls this function when a device
* reports absent, OR when the device cannot be communicated with
* @sbdev: Device that cannot be reached, or that sent report absent
*/
void slim_report_absent(struct slim_device *sbdev);
/*
* slim_framer_booted: This function is called by controller after the active
* framer has booted (using Bus Reset sequence, or after it has shutdown and has
* come back up). Components, devices on the bus may be in undefined state,
* and this function triggers their drivers to do the needful
* to bring them back in Reset state so that they can acquire sync, report
* present and be operational again.
*/
void slim_framer_booted(struct slim_controller *ctrl);
/*
* slim_msg_response: Deliver Message response received from a device to the
* framework.
* @ctrl: Controller handle
* @reply: Reply received from the device
* @len: Length of the reply
* @tid: Transaction ID received with which framework can associate reply.
* Called by controller to inform framework about the response received.
* This helps in making the API asynchronous, and controller-driver doesn't need
* to manage 1 more table other than the one managed by framework mapping TID
* with buffers
*/
extern void slim_msg_response(struct slim_controller *ctrl, u8 *reply, u8 tid,
u8 len);
/*
* slim_busnum_to_ctrl: Map bus number to controller
* @busnum: Bus number
* Returns controller representing this bus number
*/
extern struct slim_controller *slim_busnum_to_ctrl(u32 busnum);
/*
* slim_ctrl_add_boarddevs: Add devices registered by board-info
* @ctrl: Controller to which these devices are to be added to.
* This API is called by controller when it is up and running.
* If devices on a controller were registered before controller,
* this will make sure that they get probed when controller is up
*/
extern void slim_ctrl_add_boarddevs(struct slim_controller *ctrl);
extern const
struct slim_device_id *slim_get_device_id(const struct slim_device *sdev);
/*
* slim_register_board_info: Board-initialization routine.
* @info: List of all devices on all controllers present on the board.
* @n: number of entries.
* API enumerates respective devices on corresponding controller.
* Called from board-init function.
*/
#ifdef CONFIG_SLIMBUS
extern int slim_register_board_info(struct slim_boardinfo const *info,
unsigned n);
#else
static inline int slim_register_board_info(struct slim_boardinfo const *info,
unsigned n)
{
return 0;
}
#endif
static inline void *slim_get_ctrldata(const struct slim_controller *dev)
{
return dev_get_drvdata(&dev->dev);
}
static inline void slim_set_ctrldata(struct slim_controller *dev, void *data)
{
dev_set_drvdata(&dev->dev, data);
}
static inline void *slim_get_devicedata(const struct slim_device *dev)
{
return dev_get_drvdata(&dev->dev);
}
static inline void slim_set_clientdata(struct slim_device *dev, void *data)
{
dev_set_drvdata(&dev->dev, data);
}
#endif /* _LINUX_SLIMBUS_H */
|