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