1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 2020-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 * SPDX-License-Identifier: MIT
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24
25 #include "common_nvswitch.h"
26 #include "regkey_nvswitch.h"
27 #include "ls10/ls10.h"
28 #include "ls10/pmgr_ls10.h"
29 #include "error_nvswitch.h"
30 #include "pmgr_nvswitch.h"
31 #include "rom_nvswitch.h"
32 #include "export_nvswitch.h"
33 #include "soe/soe_nvswitch.h"
34 #include "soe/soeifcore.h"
35 #include "boards_nvswitch.h"
36
37 #include "nvswitch/ls10/dev_pmgr.h"
38
39 static NvBool
_nvswitch_i2c_ports_priv_locked_ls10(nvswitch_device * device)40 _nvswitch_i2c_ports_priv_locked_ls10
41 (
42 nvswitch_device *device
43 )
44 {
45 NvU32 regVal;
46
47 regVal = NVSWITCH_REG_RD32(device, _PMGR, _I2C_PRIV_LEVEL_MASK(NVSWITCH_I2C_PORT_I2CA));
48 if (FLD_TEST_DRF(_PMGR, _I2C_PRIV_LEVEL_MASK, _WRITE_PROTECTION_LEVEL0, _DISABLE, regVal))
49 {
50 return NV_TRUE;
51 }
52
53 regVal = NVSWITCH_REG_RD32(device, _PMGR, _I2C_PRIV_LEVEL_MASK(NVSWITCH_I2C_PORT_I2CB));
54 if (FLD_TEST_DRF(_PMGR, _I2C_PRIV_LEVEL_MASK, _WRITE_PROTECTION_LEVEL0, _DISABLE, regVal))
55 {
56 return NV_TRUE;
57 }
58
59 regVal = NVSWITCH_REG_RD32(device, _PMGR, _I2C_PRIV_LEVEL_MASK(NVSWITCH_I2C_PORT_I2CC));
60 if (FLD_TEST_DRF(_PMGR, _I2C_PRIV_LEVEL_MASK, _WRITE_PROTECTION_LEVEL0, _DISABLE, regVal))
61 {
62 return NV_TRUE;
63 }
64
65 return NV_FALSE;
66 }
67
68 static NvlStatus
_nvswitch_i2c_init_soe_ls10(nvswitch_device * device)69 _nvswitch_i2c_init_soe_ls10
70 (
71 nvswitch_device *device
72 )
73 {
74 NvlStatus ret;
75 PNVSWITCH_OBJI2C pI2c;
76
77 pI2c = device->pI2c;
78
79 if (!nvswitch_is_soe_supported(device))
80 {
81 return -NVL_ERR_NOT_SUPPORTED;
82 }
83
84 // Setup DMA
85 ret = nvswitch_os_alloc_contig_memory(device->os_handle, &pI2c->pCpuAddr, SOE_I2C_DMA_BUF_SIZE,
86 (device->dma_addr_width == 32));
87 if (ret != NVL_SUCCESS)
88 {
89 NVSWITCH_PRINT(device, ERROR, "%s: nvswitch_os_alloc_contig_memory returned %d\n", __FUNCTION__, ret);
90 return ret;
91 }
92
93 nvswitch_os_memset(pI2c->pCpuAddr, 0, SOE_I2C_DMA_BUF_SIZE);
94
95 ret = nvswitch_os_map_dma_region(device->os_handle, pI2c->pCpuAddr, &pI2c->dmaHandle,
96 SOE_I2C_DMA_BUF_SIZE, NVSWITCH_DMA_DIR_BIDIRECTIONAL);
97 if (ret != NVL_SUCCESS)
98 {
99 NVSWITCH_PRINT(device, ERROR, "%s: nvswitch_os_map_dma_region returned %d\n", __FUNCTION__, ret);
100 nvswitch_os_free_contig_memory(device->os_handle, pI2c->pCpuAddr, SOE_I2C_DMA_BUF_SIZE);
101 pI2c->pCpuAddr = NULL;
102 return ret;
103 }
104
105 return NVL_SUCCESS;
106 }
107
108 /*! @brief Set up a port to use a PMGR implementation.
109 *
110 * @param[in] device NvSwitch device
111 * @param[in] port The port identifier for the bus.
112 */
113 static void
_nvswitch_i2c_set_port_pmgr_ls10(nvswitch_device * device,NvU32 port)114 _nvswitch_i2c_set_port_pmgr_ls10
115 (
116 nvswitch_device *device,
117 NvU32 port
118 )
119 {
120 PNVSWITCH_OBJI2C pI2c = device->pI2c;
121
122 NVSWITCH_ASSERT(port < NVSWITCH_MAX_I2C_PORTS);
123
124 pI2c->PortInfo[port] = FLD_SET_DRF(_I2C, _PORTINFO, _DEFINED, _PRESENT, pI2c->PortInfo[port]);
125 pI2c->Ports[port].defaultSpeedMode = NVSWITCH_I2C_SPEED_MODE_100KHZ;
126 pI2c->PortInfo[port] = FLD_SET_DRF(_I2C, _PORTINFO,
127 _ACCESS_ALLOWED, _TRUE,
128 pI2c->PortInfo[port]);
129 }
130
131 //
132 // Pre-initialize the software & hardware state of the switch I2C & GPIO interface
133 //
134 void
nvswitch_init_pmgr_ls10(nvswitch_device * device)135 nvswitch_init_pmgr_ls10
136 (
137 nvswitch_device *device
138 )
139 {
140 PNVSWITCH_OBJI2C pI2c;
141
142 // Initialize I2C object
143 nvswitch_i2c_init(device);
144
145 pI2c = device->pI2c;
146
147 if (pI2c != NULL)
148 {
149 pI2c->kernelI2CSupported = NV_TRUE;
150 pI2c->soeI2CSupported = NV_TRUE;
151
152 if (_nvswitch_i2c_ports_priv_locked_ls10(device))
153 {
154 NVSWITCH_PRINT(device, WARN, "%s: I2C ports priv locked!\n", __FUNCTION__);
155 pI2c->kernelI2CSupported = NV_FALSE;
156 }
157
158 if (_nvswitch_i2c_init_soe_ls10(device) != NVL_SUCCESS)
159 {
160 pI2c->soeI2CSupported = NV_FALSE;
161 }
162
163 // Setup the 3 I2C ports
164 _nvswitch_i2c_set_port_pmgr_ls10(device, NVSWITCH_I2C_PORT_I2CA);
165 _nvswitch_i2c_set_port_pmgr_ls10(device, NVSWITCH_I2C_PORT_I2CB);
166 _nvswitch_i2c_set_port_pmgr_ls10(device, NVSWITCH_I2C_PORT_I2CC);
167 }
168
169 }
170
171 static const NVSWITCH_GPIO_INFO nvswitch_gpio_pin_Default[] =
172 {
173 NVSWITCH_DESCRIBE_GPIO_PIN( 0, _INSTANCE_ID0, 0, IN), // Instance ID bit 0
174 NVSWITCH_DESCRIBE_GPIO_PIN( 1, _INSTANCE_ID1, 0, IN), // Instance ID bit 1
175 NVSWITCH_DESCRIBE_GPIO_PIN( 2, _INSTANCE_ID2, 0, IN), // Instance ID bit 2
176 };
177
178 static const NvU32 nvswitch_gpio_pin_Default_size = NV_ARRAY_ELEMENTS(nvswitch_gpio_pin_Default);
179
180 static const NVSWITCH_GPIO_INFO nvswitch_gpio_pin_4300[] =
181 {
182 NVSWITCH_DESCRIBE_GPIO_PIN( 0, _INSTANCE_ID0, 0, IN), // Instance ID bit 0
183 NVSWITCH_DESCRIBE_GPIO_PIN( 1, _INSTANCE_ID1, 0, IN), // Instance ID bit 1
184 NVSWITCH_DESCRIBE_GPIO_PIN( 2, _INSTANCE_ID2, 0, IN), // Instance ID bit 2
185 NVSWITCH_DESCRIBE_GPIO_PIN( 6, _INSTANCE_ID3, 0, IN), // Instance ID bit 3
186 NVSWITCH_DESCRIBE_GPIO_PIN( 7, _INSTANCE_ID4, 0, IN), // Instance ID bit 4
187 };
188 static const NvU32 nvswitch_gpio_pin_4300_size = NV_ARRAY_ELEMENTS(nvswitch_gpio_pin_4300);
189
190 //
191 // Initialize the software state of the switch I2C & GPIO interface
192 // Temporarily forcing default GPIO values.
193 //
194
195 // TODO: This function should be updated with the board values from DCB.
196
197 void
nvswitch_init_pmgr_devices_ls10(nvswitch_device * device)198 nvswitch_init_pmgr_devices_ls10
199 (
200 nvswitch_device *device
201 )
202 {
203 ls10_device *chip_device = NVSWITCH_GET_CHIP_DEVICE_LS10(device);
204 PNVSWITCH_OBJI2C pI2c = device->pI2c;
205 NvlStatus retval;
206 NvU16 boardId;
207
208 if (IS_FMODEL(device) || IS_EMULATION(device) || IS_RTLSIM(device))
209 {
210 // GPIOs not modelled on non-silicon
211 chip_device->gpio_pin = NULL;
212 chip_device->gpio_pin_size = 0;
213 }
214 else
215 {
216 retval = nvswitch_get_board_id(device, &boardId);
217 if (retval == NVL_SUCCESS &&
218 boardId == NVSWITCH_BOARD_LS10_4300_0000_895)
219 {
220 chip_device->gpio_pin = nvswitch_gpio_pin_4300;
221 chip_device->gpio_pin_size = nvswitch_gpio_pin_4300_size;
222 }
223 else
224 {
225 chip_device->gpio_pin = nvswitch_gpio_pin_Default;
226 chip_device->gpio_pin_size = nvswitch_gpio_pin_Default_size;
227 }
228 }
229
230 pI2c->device_list = NULL;
231 pI2c->device_list_size = 0;
232 }
233
234 NvlStatus
nvswitch_get_rom_info_ls10(nvswitch_device * device,NVSWITCH_EEPROM_TYPE * eeprom)235 nvswitch_get_rom_info_ls10
236 (
237 nvswitch_device *device,
238 NVSWITCH_EEPROM_TYPE *eeprom
239 )
240 {
241 NVSWITCH_PRINT(device, WARN, "%s: Function not implemented\n", __FUNCTION__);
242 return NVL_SUCCESS;
243 }
244
245 /*!
246 * RM Control command to determine the physical id of the device.
247 */
248 NvU32
nvswitch_read_physical_id_ls10(nvswitch_device * device)249 nvswitch_read_physical_id_ls10
250 (
251 nvswitch_device *device
252 )
253 {
254 ls10_device *chip_device = NVSWITCH_GET_CHIP_DEVICE_LS10(device);
255 NvU32 physical_id = 0;
256 NvU32 data;
257 NvU32 idx_gpio;
258 NvU32 input_inv;
259 NvU32 function_offset;
260
261 for (idx_gpio = 0; idx_gpio < chip_device->gpio_pin_size; idx_gpio++)
262 {
263 if ((chip_device->gpio_pin[idx_gpio].function >= NVSWITCH_GPIO_ENTRY_FUNCTION_INSTANCE_ID0) &&
264 (chip_device->gpio_pin[idx_gpio].function <= NVSWITCH_GPIO_ENTRY_FUNCTION_INSTANCE_ID6))
265 {
266 if (chip_device->gpio_pin[idx_gpio].misc == NVSWITCH_GPIO_ENTRY_MISC_IO_INV_IN)
267 {
268 input_inv = NV_PMGR_GPIO_INPUT_CNTL_1_INV_YES;
269 }
270 else
271 {
272 input_inv = NV_PMGR_GPIO_INPUT_CNTL_1_INV_NO;
273 }
274
275 NVSWITCH_REG_WR32(device, _PMGR, _GPIO_INPUT_CNTL_1,
276 DRF_NUM(_PMGR, _GPIO_INPUT_CNTL_1, _PINNUM, chip_device->gpio_pin[idx_gpio].pin) |
277 DRF_NUM(_PMGR, _GPIO_INPUT_CNTL_1, _INV, input_inv) |
278 DRF_DEF(_PMGR, _GPIO_INPUT_CNTL_1, _BYPASS_FILTER, _NO));
279
280 data = NVSWITCH_REG_RD32(device, _PMGR, _GPIO_INPUT_CNTL_1);
281 function_offset = chip_device->gpio_pin[idx_gpio].function -
282 NVSWITCH_GPIO_ENTRY_FUNCTION_INSTANCE_ID0;
283 physical_id |=
284 (DRF_VAL(_PMGR, _GPIO_INPUT_CNTL_1, _READ, data) << function_offset);
285 }
286 }
287
288 NVSWITCH_PRINT(device, SETUP, "%s Device position Id = 0x%x\n", __FUNCTION__, physical_id);
289
290 return physical_id;
291 }
292
293 /*!
294 * RM Control command to perform indexed I2C.
295 */
296 NvlStatus
nvswitch_ctrl_i2c_indexed_ls10(nvswitch_device * device,NVSWITCH_CTRL_I2C_INDEXED_PARAMS * pParams)297 nvswitch_ctrl_i2c_indexed_ls10
298 (
299 nvswitch_device *device,
300 NVSWITCH_CTRL_I2C_INDEXED_PARAMS *pParams
301 )
302 {
303 PNVSWITCH_OBJI2C pI2c;
304
305 pI2c = device->pI2c;
306
307 if (pI2c == NULL)
308 {
309 return -NVL_ERR_NOT_SUPPORTED;
310 }
311
312 if (pParams == NULL)
313 {
314 return -NVL_BAD_ARGS;
315 }
316
317 // SW I2C only supported by kernel driver
318 if (device->regkeys.force_kernel_i2c == NV_SWITCH_REGKEY_FORCE_KERNEL_I2C_ENABLE ||
319 FLD_TEST_DRF(SWITCH_CTRL, _I2C_FLAGS, _FLAVOR, _SW, pParams->flags))
320 {
321 if (!pI2c->kernelI2CSupported)
322 {
323 return -NVL_ERR_NOT_SUPPORTED;
324 }
325 return nvswitch_ctrl_i2c_indexed_lr10(device, pParams);
326 }
327
328 if (pParams->port == NVSWITCH_I2C_PORT_I2CA)
329 {
330 pParams->flags = FLD_SET_DRF(SWITCH_CTRL, _I2C_FLAGS, _SPEED_MODE, _100KHZ, pParams->flags);
331 }
332
333 if (pI2c->soeI2CSupported)
334 {
335 return soeI2CAccess_HAL(device, pParams);
336 }
337
338 return -NVL_ERR_NOT_SUPPORTED;
339 }
340
341 /*!
342 * Return if I2C transactions can be supported.
343 *
344 * @param[in] device The NvSwitch Device.
345 *
346 */
347 NvBool
nvswitch_is_i2c_supported_ls10(nvswitch_device * device)348 nvswitch_is_i2c_supported_ls10
349 (
350 nvswitch_device *device
351 )
352 {
353 return ((device->pI2c != NULL) &&
354 (device->pI2c->soeI2CSupported || device->pI2c->kernelI2CSupported));
355 }
356
357 /*!
358 * Return if I2C device and port is allowed access
359 *
360 * @param[in] device The NvSwitch Device.
361 * @param[in] port The I2C Port.
362 * @param[in] addr The I2C device to access.
363 * @param[in] bIsRead Boolean if I2C transaction is a read.
364 *
365 */
366 NvBool
nvswitch_i2c_is_device_access_allowed_ls10(nvswitch_device * device,NvU32 port,NvU8 addr,NvBool bIsRead)367 nvswitch_i2c_is_device_access_allowed_ls10
368 (
369 nvswitch_device *device,
370 NvU32 port,
371 NvU8 addr,
372 NvBool bIsRead
373 )
374 {
375 // Check will be performed in SOE
376 return NV_TRUE;
377 }
378