hc
2023-12-06 08f87f769b595151be1afeff53e144f543faa614
kernel/drivers/bus/fsl-mc/dprc.c
....@@ -1,12 +1,20 @@
11 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
22 /*
33 * Copyright 2013-2016 Freescale Semiconductor Inc.
4
+ * Copyright 2020 NXP
45 *
56 */
67 #include <linux/kernel.h>
78 #include <linux/fsl/mc.h>
89
910 #include "fsl-mc-private.h"
11
+
12
+/*
13
+ * cache the DPRC version to reduce the number of commands
14
+ * towards the mc firmware
15
+ */
16
+static u16 dprc_major_ver;
17
+static u16 dprc_minor_ver;
1018
1119 /**
1220 * dprc_open() - Open DPRC object for use
....@@ -71,6 +79,77 @@
7179 return mc_send_command(mc_io, &cmd);
7280 }
7381 EXPORT_SYMBOL_GPL(dprc_close);
82
+
83
+/**
84
+ * dprc_reset_container - Reset child container.
85
+ * @mc_io: Pointer to MC portal's I/O object
86
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
87
+ * @token: Token of DPRC object
88
+ * @child_container_id: ID of the container to reset
89
+ * @options: 32 bit options:
90
+ * - 0 (no bits set) - all the objects inside the container are
91
+ * reset. The child containers are entered recursively and the
92
+ * objects reset. All the objects (including the child containers)
93
+ * are closed.
94
+ * - bit 0 set - all the objects inside the container are reset.
95
+ * However the child containers are not entered recursively.
96
+ * This option is supported for API versions >= 6.5
97
+ * In case a software context crashes or becomes non-responsive, the parent
98
+ * may wish to reset its resources container before the software context is
99
+ * restarted.
100
+ *
101
+ * This routine informs all objects assigned to the child container that the
102
+ * container is being reset, so they may perform any cleanup operations that are
103
+ * needed. All objects handles that were owned by the child container shall be
104
+ * closed.
105
+ *
106
+ * Note that such request may be submitted even if the child software context
107
+ * has not crashed, but the resulting object cleanup operations will not be
108
+ * aware of that.
109
+ *
110
+ * Return: '0' on Success; Error code otherwise.
111
+ */
112
+int dprc_reset_container(struct fsl_mc_io *mc_io,
113
+ u32 cmd_flags,
114
+ u16 token,
115
+ int child_container_id,
116
+ u32 options)
117
+{
118
+ struct fsl_mc_command cmd = { 0 };
119
+ struct dprc_cmd_reset_container *cmd_params;
120
+ u32 cmdid = DPRC_CMDID_RESET_CONT;
121
+ int err;
122
+
123
+ /*
124
+ * If the DPRC object version was not yet cached, cache it now.
125
+ * Otherwise use the already cached value.
126
+ */
127
+ if (!dprc_major_ver && !dprc_minor_ver) {
128
+ err = dprc_get_api_version(mc_io, 0,
129
+ &dprc_major_ver,
130
+ &dprc_minor_ver);
131
+ if (err)
132
+ return err;
133
+ }
134
+
135
+ /*
136
+ * MC API 6.5 introduced a new field in the command used to pass
137
+ * some flags.
138
+ * Bit 0 indicates that the child containers are not recursively reset.
139
+ */
140
+ if (dprc_major_ver > 6 || (dprc_major_ver == 6 && dprc_minor_ver >= 5))
141
+ cmdid = DPRC_CMDID_RESET_CONT_V2;
142
+
143
+ /* prepare command */
144
+ cmd.header = mc_encode_cmd_header(cmdid, cmd_flags, token);
145
+ cmd_params = (struct dprc_cmd_reset_container *)cmd.params;
146
+ cmd_params->child_container_id = cpu_to_le32(child_container_id);
147
+ cmd_params->options = cpu_to_le32(options);
148
+
149
+ /* send command to mc*/
150
+ return mc_send_command(mc_io, &cmd);
151
+}
152
+EXPORT_SYMBOL_GPL(dprc_reset_container);
74153
75154 /**
76155 * dprc_set_irq() - Set IRQ information for the DPRC to trigger an interrupt.
....@@ -281,7 +360,7 @@
281360 /* retrieve response parameters */
282361 rsp_params = (struct dprc_rsp_get_attributes *)cmd.params;
283362 attr->container_id = le32_to_cpu(rsp_params->container_id);
284
- attr->icid = le16_to_cpu(rsp_params->icid);
363
+ attr->icid = le32_to_cpu(rsp_params->icid);
285364 attr->options = le32_to_cpu(rsp_params->options);
286365 attr->portal_id = le32_to_cpu(rsp_params->portal_id);
287366
....@@ -445,9 +524,43 @@
445524 struct dprc_rsp_get_obj_region *rsp_params;
446525 int err;
447526
448
- /* prepare command */
449
- cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG,
450
- cmd_flags, token);
527
+ /*
528
+ * If the DPRC object version was not yet cached, cache it now.
529
+ * Otherwise use the already cached value.
530
+ */
531
+ if (!dprc_major_ver && !dprc_minor_ver) {
532
+ err = dprc_get_api_version(mc_io, 0,
533
+ &dprc_major_ver,
534
+ &dprc_minor_ver);
535
+ if (err)
536
+ return err;
537
+ }
538
+
539
+ if (dprc_major_ver > 6 || (dprc_major_ver == 6 && dprc_minor_ver >= 6)) {
540
+ /*
541
+ * MC API version 6.6 changed the size of the MC portals and software
542
+ * portals to 64K (as implemented by hardware). If older API is in use the
543
+ * size reported is less (64 bytes for mc portals and 4K for software
544
+ * portals).
545
+ */
546
+
547
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG_V3,
548
+ cmd_flags, token);
549
+
550
+ } else if (dprc_major_ver == 6 && dprc_minor_ver >= 3) {
551
+ /*
552
+ * MC API version 6.3 introduced a new field to the region
553
+ * descriptor: base_address. If the older API is in use then the base
554
+ * address is set to zero to indicate it needs to be obtained elsewhere
555
+ * (typically the device tree).
556
+ */
557
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG_V2,
558
+ cmd_flags, token);
559
+ } else {
560
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG,
561
+ cmd_flags, token);
562
+ }
563
+
451564 cmd_params = (struct dprc_cmd_get_obj_region *)cmd.params;
452565 cmd_params->obj_id = cpu_to_le32(obj_id);
453566 cmd_params->region_index = region_index;
....@@ -461,8 +574,12 @@
461574
462575 /* retrieve response parameters */
463576 rsp_params = (struct dprc_rsp_get_obj_region *)cmd.params;
464
- region_desc->base_offset = le64_to_cpu(rsp_params->base_addr);
577
+ region_desc->base_offset = le64_to_cpu(rsp_params->base_offset);
465578 region_desc->size = le32_to_cpu(rsp_params->size);
579
+ if (dprc_major_ver > 6 || (dprc_major_ver == 6 && dprc_minor_ver >= 3))
580
+ region_desc->base_address = le64_to_cpu(rsp_params->base_addr);
581
+ else
582
+ region_desc->base_address = 0;
466583
467584 return 0;
468585 }
....@@ -530,3 +647,56 @@
530647
531648 return 0;
532649 }
650
+
651
+/**
652
+ * dprc_get_connection() - Get connected endpoint and link status if connection
653
+ * exists.
654
+ * @mc_io: Pointer to MC portal's I/O object
655
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
656
+ * @token: Token of DPRC object
657
+ * @endpoint1: Endpoint 1 configuration parameters
658
+ * @endpoint2: Returned endpoint 2 configuration parameters
659
+ * @state: Returned link state:
660
+ * 1 - link is up;
661
+ * 0 - link is down;
662
+ * -1 - no connection (endpoint2 information is irrelevant)
663
+ *
664
+ * Return: '0' on Success; -ENOTCONN if connection does not exist.
665
+ */
666
+int dprc_get_connection(struct fsl_mc_io *mc_io,
667
+ u32 cmd_flags,
668
+ u16 token,
669
+ const struct dprc_endpoint *endpoint1,
670
+ struct dprc_endpoint *endpoint2,
671
+ int *state)
672
+{
673
+ struct dprc_cmd_get_connection *cmd_params;
674
+ struct dprc_rsp_get_connection *rsp_params;
675
+ struct fsl_mc_command cmd = { 0 };
676
+ int err, i;
677
+
678
+ /* prepare command */
679
+ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONNECTION,
680
+ cmd_flags,
681
+ token);
682
+ cmd_params = (struct dprc_cmd_get_connection *)cmd.params;
683
+ cmd_params->ep1_id = cpu_to_le32(endpoint1->id);
684
+ cmd_params->ep1_interface_id = cpu_to_le16(endpoint1->if_id);
685
+ for (i = 0; i < 16; i++)
686
+ cmd_params->ep1_type[i] = endpoint1->type[i];
687
+
688
+ /* send command to mc */
689
+ err = mc_send_command(mc_io, &cmd);
690
+ if (err)
691
+ return -ENOTCONN;
692
+
693
+ /* retrieve response parameters */
694
+ rsp_params = (struct dprc_rsp_get_connection *)cmd.params;
695
+ endpoint2->id = le32_to_cpu(rsp_params->ep2_id);
696
+ endpoint2->if_id = le16_to_cpu(rsp_params->ep2_interface_id);
697
+ *state = le32_to_cpu(rsp_params->state);
698
+ for (i = 0; i < 16; i++)
699
+ endpoint2->type[i] = rsp_params->ep2_type[i];
700
+
701
+ return 0;
702
+}