18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Xilinx VCU Init 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2016 - 2017 Xilinx, Inc. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Contacts Dhaval Shah <dshah@xilinx.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include <linux/clk.h> 108c2ecf20Sopenharmony_ci#include <linux/device.h> 118c2ecf20Sopenharmony_ci#include <linux/errno.h> 128c2ecf20Sopenharmony_ci#include <linux/io.h> 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 158c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci/* Address map for different registers implemented in the VCU LogiCORE IP. */ 188c2ecf20Sopenharmony_ci#define VCU_ECODER_ENABLE 0x00 198c2ecf20Sopenharmony_ci#define VCU_DECODER_ENABLE 0x04 208c2ecf20Sopenharmony_ci#define VCU_MEMORY_DEPTH 0x08 218c2ecf20Sopenharmony_ci#define VCU_ENC_COLOR_DEPTH 0x0c 228c2ecf20Sopenharmony_ci#define VCU_ENC_VERTICAL_RANGE 0x10 238c2ecf20Sopenharmony_ci#define VCU_ENC_FRAME_SIZE_X 0x14 248c2ecf20Sopenharmony_ci#define VCU_ENC_FRAME_SIZE_Y 0x18 258c2ecf20Sopenharmony_ci#define VCU_ENC_COLOR_FORMAT 0x1c 268c2ecf20Sopenharmony_ci#define VCU_ENC_FPS 0x20 278c2ecf20Sopenharmony_ci#define VCU_MCU_CLK 0x24 288c2ecf20Sopenharmony_ci#define VCU_CORE_CLK 0x28 298c2ecf20Sopenharmony_ci#define VCU_PLL_BYPASS 0x2c 308c2ecf20Sopenharmony_ci#define VCU_ENC_CLK 0x30 318c2ecf20Sopenharmony_ci#define VCU_PLL_CLK 0x34 328c2ecf20Sopenharmony_ci#define VCU_ENC_VIDEO_STANDARD 0x38 338c2ecf20Sopenharmony_ci#define VCU_STATUS 0x3c 348c2ecf20Sopenharmony_ci#define VCU_AXI_ENC_CLK 0x40 358c2ecf20Sopenharmony_ci#define VCU_AXI_DEC_CLK 0x44 368c2ecf20Sopenharmony_ci#define VCU_AXI_MCU_CLK 0x48 378c2ecf20Sopenharmony_ci#define VCU_DEC_VIDEO_STANDARD 0x4c 388c2ecf20Sopenharmony_ci#define VCU_DEC_FRAME_SIZE_X 0x50 398c2ecf20Sopenharmony_ci#define VCU_DEC_FRAME_SIZE_Y 0x54 408c2ecf20Sopenharmony_ci#define VCU_DEC_FPS 0x58 418c2ecf20Sopenharmony_ci#define VCU_BUFFER_B_FRAME 0x5c 428c2ecf20Sopenharmony_ci#define VCU_WPP_EN 0x60 438c2ecf20Sopenharmony_ci#define VCU_PLL_CLK_DEC 0x64 448c2ecf20Sopenharmony_ci#define VCU_GASKET_INIT 0x74 458c2ecf20Sopenharmony_ci#define VCU_GASKET_VALUE 0x03 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci/* vcu slcr registers, bitmask and shift */ 488c2ecf20Sopenharmony_ci#define VCU_PLL_CTRL 0x24 498c2ecf20Sopenharmony_ci#define VCU_PLL_CTRL_RESET_MASK 0x01 508c2ecf20Sopenharmony_ci#define VCU_PLL_CTRL_RESET_SHIFT 0 518c2ecf20Sopenharmony_ci#define VCU_PLL_CTRL_BYPASS_MASK 0x01 528c2ecf20Sopenharmony_ci#define VCU_PLL_CTRL_BYPASS_SHIFT 3 538c2ecf20Sopenharmony_ci#define VCU_PLL_CTRL_FBDIV_MASK 0x7f 548c2ecf20Sopenharmony_ci#define VCU_PLL_CTRL_FBDIV_SHIFT 8 558c2ecf20Sopenharmony_ci#define VCU_PLL_CTRL_POR_IN_MASK 0x01 568c2ecf20Sopenharmony_ci#define VCU_PLL_CTRL_POR_IN_SHIFT 1 578c2ecf20Sopenharmony_ci#define VCU_PLL_CTRL_PWR_POR_MASK 0x01 588c2ecf20Sopenharmony_ci#define VCU_PLL_CTRL_PWR_POR_SHIFT 2 598c2ecf20Sopenharmony_ci#define VCU_PLL_CTRL_CLKOUTDIV_MASK 0x03 608c2ecf20Sopenharmony_ci#define VCU_PLL_CTRL_CLKOUTDIV_SHIFT 16 618c2ecf20Sopenharmony_ci#define VCU_PLL_CTRL_DEFAULT 0 628c2ecf20Sopenharmony_ci#define VCU_PLL_DIV2 2 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci#define VCU_PLL_CFG 0x28 658c2ecf20Sopenharmony_ci#define VCU_PLL_CFG_RES_MASK 0x0f 668c2ecf20Sopenharmony_ci#define VCU_PLL_CFG_RES_SHIFT 0 678c2ecf20Sopenharmony_ci#define VCU_PLL_CFG_CP_MASK 0x0f 688c2ecf20Sopenharmony_ci#define VCU_PLL_CFG_CP_SHIFT 5 698c2ecf20Sopenharmony_ci#define VCU_PLL_CFG_LFHF_MASK 0x03 708c2ecf20Sopenharmony_ci#define VCU_PLL_CFG_LFHF_SHIFT 10 718c2ecf20Sopenharmony_ci#define VCU_PLL_CFG_LOCK_CNT_MASK 0x03ff 728c2ecf20Sopenharmony_ci#define VCU_PLL_CFG_LOCK_CNT_SHIFT 13 738c2ecf20Sopenharmony_ci#define VCU_PLL_CFG_LOCK_DLY_MASK 0x7f 748c2ecf20Sopenharmony_ci#define VCU_PLL_CFG_LOCK_DLY_SHIFT 25 758c2ecf20Sopenharmony_ci#define VCU_ENC_CORE_CTRL 0x30 768c2ecf20Sopenharmony_ci#define VCU_ENC_MCU_CTRL 0x34 778c2ecf20Sopenharmony_ci#define VCU_DEC_CORE_CTRL 0x38 788c2ecf20Sopenharmony_ci#define VCU_DEC_MCU_CTRL 0x3c 798c2ecf20Sopenharmony_ci#define VCU_PLL_DIVISOR_MASK 0x3f 808c2ecf20Sopenharmony_ci#define VCU_PLL_DIVISOR_SHIFT 4 818c2ecf20Sopenharmony_ci#define VCU_SRCSEL_MASK 0x01 828c2ecf20Sopenharmony_ci#define VCU_SRCSEL_SHIFT 0 838c2ecf20Sopenharmony_ci#define VCU_SRCSEL_PLL 1 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci#define VCU_PLL_STATUS 0x60 868c2ecf20Sopenharmony_ci#define VCU_PLL_STATUS_LOCK_STATUS_MASK 0x01 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci#define MHZ 1000000 898c2ecf20Sopenharmony_ci#define FVCO_MIN (1500U * MHZ) 908c2ecf20Sopenharmony_ci#define FVCO_MAX (3000U * MHZ) 918c2ecf20Sopenharmony_ci#define DIVISOR_MIN 0 928c2ecf20Sopenharmony_ci#define DIVISOR_MAX 63 938c2ecf20Sopenharmony_ci#define FRAC 100 948c2ecf20Sopenharmony_ci#define LIMIT (10 * MHZ) 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci/** 978c2ecf20Sopenharmony_ci * struct xvcu_device - Xilinx VCU init device structure 988c2ecf20Sopenharmony_ci * @dev: Platform device 998c2ecf20Sopenharmony_ci * @pll_ref: pll ref clock source 1008c2ecf20Sopenharmony_ci * @aclk: axi clock source 1018c2ecf20Sopenharmony_ci * @logicore_reg_ba: logicore reg base address 1028c2ecf20Sopenharmony_ci * @vcu_slcr_ba: vcu_slcr Register base address 1038c2ecf20Sopenharmony_ci * @coreclk: core clock frequency 1048c2ecf20Sopenharmony_ci */ 1058c2ecf20Sopenharmony_cistruct xvcu_device { 1068c2ecf20Sopenharmony_ci struct device *dev; 1078c2ecf20Sopenharmony_ci struct clk *pll_ref; 1088c2ecf20Sopenharmony_ci struct clk *aclk; 1098c2ecf20Sopenharmony_ci void __iomem *logicore_reg_ba; 1108c2ecf20Sopenharmony_ci void __iomem *vcu_slcr_ba; 1118c2ecf20Sopenharmony_ci u32 coreclk; 1128c2ecf20Sopenharmony_ci}; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci/** 1158c2ecf20Sopenharmony_ci * struct xvcu_pll_cfg - Helper data 1168c2ecf20Sopenharmony_ci * @fbdiv: The integer portion of the feedback divider to the PLL 1178c2ecf20Sopenharmony_ci * @cp: PLL charge pump control 1188c2ecf20Sopenharmony_ci * @res: PLL loop filter resistor control 1198c2ecf20Sopenharmony_ci * @lfhf: PLL loop filter high frequency capacitor control 1208c2ecf20Sopenharmony_ci * @lock_dly: Lock circuit configuration settings for lock windowsize 1218c2ecf20Sopenharmony_ci * @lock_cnt: Lock circuit counter setting 1228c2ecf20Sopenharmony_ci */ 1238c2ecf20Sopenharmony_cistruct xvcu_pll_cfg { 1248c2ecf20Sopenharmony_ci u32 fbdiv; 1258c2ecf20Sopenharmony_ci u32 cp; 1268c2ecf20Sopenharmony_ci u32 res; 1278c2ecf20Sopenharmony_ci u32 lfhf; 1288c2ecf20Sopenharmony_ci u32 lock_dly; 1298c2ecf20Sopenharmony_ci u32 lock_cnt; 1308c2ecf20Sopenharmony_ci}; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic const struct xvcu_pll_cfg xvcu_pll_cfg[] = { 1338c2ecf20Sopenharmony_ci { 25, 3, 10, 3, 63, 1000 }, 1348c2ecf20Sopenharmony_ci { 26, 3, 10, 3, 63, 1000 }, 1358c2ecf20Sopenharmony_ci { 27, 4, 6, 3, 63, 1000 }, 1368c2ecf20Sopenharmony_ci { 28, 4, 6, 3, 63, 1000 }, 1378c2ecf20Sopenharmony_ci { 29, 4, 6, 3, 63, 1000 }, 1388c2ecf20Sopenharmony_ci { 30, 4, 6, 3, 63, 1000 }, 1398c2ecf20Sopenharmony_ci { 31, 6, 1, 3, 63, 1000 }, 1408c2ecf20Sopenharmony_ci { 32, 6, 1, 3, 63, 1000 }, 1418c2ecf20Sopenharmony_ci { 33, 4, 10, 3, 63, 1000 }, 1428c2ecf20Sopenharmony_ci { 34, 5, 6, 3, 63, 1000 }, 1438c2ecf20Sopenharmony_ci { 35, 5, 6, 3, 63, 1000 }, 1448c2ecf20Sopenharmony_ci { 36, 5, 6, 3, 63, 1000 }, 1458c2ecf20Sopenharmony_ci { 37, 5, 6, 3, 63, 1000 }, 1468c2ecf20Sopenharmony_ci { 38, 5, 6, 3, 63, 975 }, 1478c2ecf20Sopenharmony_ci { 39, 3, 12, 3, 63, 950 }, 1488c2ecf20Sopenharmony_ci { 40, 3, 12, 3, 63, 925 }, 1498c2ecf20Sopenharmony_ci { 41, 3, 12, 3, 63, 900 }, 1508c2ecf20Sopenharmony_ci { 42, 3, 12, 3, 63, 875 }, 1518c2ecf20Sopenharmony_ci { 43, 3, 12, 3, 63, 850 }, 1528c2ecf20Sopenharmony_ci { 44, 3, 12, 3, 63, 850 }, 1538c2ecf20Sopenharmony_ci { 45, 3, 12, 3, 63, 825 }, 1548c2ecf20Sopenharmony_ci { 46, 3, 12, 3, 63, 800 }, 1558c2ecf20Sopenharmony_ci { 47, 3, 12, 3, 63, 775 }, 1568c2ecf20Sopenharmony_ci { 48, 3, 12, 3, 63, 775 }, 1578c2ecf20Sopenharmony_ci { 49, 3, 12, 3, 63, 750 }, 1588c2ecf20Sopenharmony_ci { 50, 3, 12, 3, 63, 750 }, 1598c2ecf20Sopenharmony_ci { 51, 3, 2, 3, 63, 725 }, 1608c2ecf20Sopenharmony_ci { 52, 3, 2, 3, 63, 700 }, 1618c2ecf20Sopenharmony_ci { 53, 3, 2, 3, 63, 700 }, 1628c2ecf20Sopenharmony_ci { 54, 3, 2, 3, 63, 675 }, 1638c2ecf20Sopenharmony_ci { 55, 3, 2, 3, 63, 675 }, 1648c2ecf20Sopenharmony_ci { 56, 3, 2, 3, 63, 650 }, 1658c2ecf20Sopenharmony_ci { 57, 3, 2, 3, 63, 650 }, 1668c2ecf20Sopenharmony_ci { 58, 3, 2, 3, 63, 625 }, 1678c2ecf20Sopenharmony_ci { 59, 3, 2, 3, 63, 625 }, 1688c2ecf20Sopenharmony_ci { 60, 3, 2, 3, 63, 625 }, 1698c2ecf20Sopenharmony_ci { 61, 3, 2, 3, 63, 600 }, 1708c2ecf20Sopenharmony_ci { 62, 3, 2, 3, 63, 600 }, 1718c2ecf20Sopenharmony_ci { 63, 3, 2, 3, 63, 600 }, 1728c2ecf20Sopenharmony_ci { 64, 3, 2, 3, 63, 600 }, 1738c2ecf20Sopenharmony_ci { 65, 3, 2, 3, 63, 600 }, 1748c2ecf20Sopenharmony_ci { 66, 3, 2, 3, 63, 600 }, 1758c2ecf20Sopenharmony_ci { 67, 3, 2, 3, 63, 600 }, 1768c2ecf20Sopenharmony_ci { 68, 3, 2, 3, 63, 600 }, 1778c2ecf20Sopenharmony_ci { 69, 3, 2, 3, 63, 600 }, 1788c2ecf20Sopenharmony_ci { 70, 3, 2, 3, 63, 600 }, 1798c2ecf20Sopenharmony_ci { 71, 3, 2, 3, 63, 600 }, 1808c2ecf20Sopenharmony_ci { 72, 3, 2, 3, 63, 600 }, 1818c2ecf20Sopenharmony_ci { 73, 3, 2, 3, 63, 600 }, 1828c2ecf20Sopenharmony_ci { 74, 3, 2, 3, 63, 600 }, 1838c2ecf20Sopenharmony_ci { 75, 3, 2, 3, 63, 600 }, 1848c2ecf20Sopenharmony_ci { 76, 3, 2, 3, 63, 600 }, 1858c2ecf20Sopenharmony_ci { 77, 3, 2, 3, 63, 600 }, 1868c2ecf20Sopenharmony_ci { 78, 3, 2, 3, 63, 600 }, 1878c2ecf20Sopenharmony_ci { 79, 3, 2, 3, 63, 600 }, 1888c2ecf20Sopenharmony_ci { 80, 3, 2, 3, 63, 600 }, 1898c2ecf20Sopenharmony_ci { 81, 3, 2, 3, 63, 600 }, 1908c2ecf20Sopenharmony_ci { 82, 3, 2, 3, 63, 600 }, 1918c2ecf20Sopenharmony_ci { 83, 4, 2, 3, 63, 600 }, 1928c2ecf20Sopenharmony_ci { 84, 4, 2, 3, 63, 600 }, 1938c2ecf20Sopenharmony_ci { 85, 4, 2, 3, 63, 600 }, 1948c2ecf20Sopenharmony_ci { 86, 4, 2, 3, 63, 600 }, 1958c2ecf20Sopenharmony_ci { 87, 4, 2, 3, 63, 600 }, 1968c2ecf20Sopenharmony_ci { 88, 4, 2, 3, 63, 600 }, 1978c2ecf20Sopenharmony_ci { 89, 4, 2, 3, 63, 600 }, 1988c2ecf20Sopenharmony_ci { 90, 4, 2, 3, 63, 600 }, 1998c2ecf20Sopenharmony_ci { 91, 4, 2, 3, 63, 600 }, 2008c2ecf20Sopenharmony_ci { 92, 4, 2, 3, 63, 600 }, 2018c2ecf20Sopenharmony_ci { 93, 4, 2, 3, 63, 600 }, 2028c2ecf20Sopenharmony_ci { 94, 4, 2, 3, 63, 600 }, 2038c2ecf20Sopenharmony_ci { 95, 4, 2, 3, 63, 600 }, 2048c2ecf20Sopenharmony_ci { 96, 4, 2, 3, 63, 600 }, 2058c2ecf20Sopenharmony_ci { 97, 4, 2, 3, 63, 600 }, 2068c2ecf20Sopenharmony_ci { 98, 4, 2, 3, 63, 600 }, 2078c2ecf20Sopenharmony_ci { 99, 4, 2, 3, 63, 600 }, 2088c2ecf20Sopenharmony_ci { 100, 4, 2, 3, 63, 600 }, 2098c2ecf20Sopenharmony_ci { 101, 4, 2, 3, 63, 600 }, 2108c2ecf20Sopenharmony_ci { 102, 4, 2, 3, 63, 600 }, 2118c2ecf20Sopenharmony_ci { 103, 5, 2, 3, 63, 600 }, 2128c2ecf20Sopenharmony_ci { 104, 5, 2, 3, 63, 600 }, 2138c2ecf20Sopenharmony_ci { 105, 5, 2, 3, 63, 600 }, 2148c2ecf20Sopenharmony_ci { 106, 5, 2, 3, 63, 600 }, 2158c2ecf20Sopenharmony_ci { 107, 3, 4, 3, 63, 600 }, 2168c2ecf20Sopenharmony_ci { 108, 3, 4, 3, 63, 600 }, 2178c2ecf20Sopenharmony_ci { 109, 3, 4, 3, 63, 600 }, 2188c2ecf20Sopenharmony_ci { 110, 3, 4, 3, 63, 600 }, 2198c2ecf20Sopenharmony_ci { 111, 3, 4, 3, 63, 600 }, 2208c2ecf20Sopenharmony_ci { 112, 3, 4, 3, 63, 600 }, 2218c2ecf20Sopenharmony_ci { 113, 3, 4, 3, 63, 600 }, 2228c2ecf20Sopenharmony_ci { 114, 3, 4, 3, 63, 600 }, 2238c2ecf20Sopenharmony_ci { 115, 3, 4, 3, 63, 600 }, 2248c2ecf20Sopenharmony_ci { 116, 3, 4, 3, 63, 600 }, 2258c2ecf20Sopenharmony_ci { 117, 3, 4, 3, 63, 600 }, 2268c2ecf20Sopenharmony_ci { 118, 3, 4, 3, 63, 600 }, 2278c2ecf20Sopenharmony_ci { 119, 3, 4, 3, 63, 600 }, 2288c2ecf20Sopenharmony_ci { 120, 3, 4, 3, 63, 600 }, 2298c2ecf20Sopenharmony_ci { 121, 3, 4, 3, 63, 600 }, 2308c2ecf20Sopenharmony_ci { 122, 3, 4, 3, 63, 600 }, 2318c2ecf20Sopenharmony_ci { 123, 3, 4, 3, 63, 600 }, 2328c2ecf20Sopenharmony_ci { 124, 3, 4, 3, 63, 600 }, 2338c2ecf20Sopenharmony_ci { 125, 3, 4, 3, 63, 600 }, 2348c2ecf20Sopenharmony_ci}; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci/** 2378c2ecf20Sopenharmony_ci * xvcu_read - Read from the VCU register space 2388c2ecf20Sopenharmony_ci * @iomem: vcu reg space base address 2398c2ecf20Sopenharmony_ci * @offset: vcu reg offset from base 2408c2ecf20Sopenharmony_ci * 2418c2ecf20Sopenharmony_ci * Return: Returns 32bit value from VCU register specified 2428c2ecf20Sopenharmony_ci * 2438c2ecf20Sopenharmony_ci */ 2448c2ecf20Sopenharmony_cistatic inline u32 xvcu_read(void __iomem *iomem, u32 offset) 2458c2ecf20Sopenharmony_ci{ 2468c2ecf20Sopenharmony_ci return ioread32(iomem + offset); 2478c2ecf20Sopenharmony_ci} 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci/** 2508c2ecf20Sopenharmony_ci * xvcu_write - Write to the VCU register space 2518c2ecf20Sopenharmony_ci * @iomem: vcu reg space base address 2528c2ecf20Sopenharmony_ci * @offset: vcu reg offset from base 2538c2ecf20Sopenharmony_ci * @value: Value to write 2548c2ecf20Sopenharmony_ci */ 2558c2ecf20Sopenharmony_cistatic inline void xvcu_write(void __iomem *iomem, u32 offset, u32 value) 2568c2ecf20Sopenharmony_ci{ 2578c2ecf20Sopenharmony_ci iowrite32(value, iomem + offset); 2588c2ecf20Sopenharmony_ci} 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci/** 2618c2ecf20Sopenharmony_ci * xvcu_write_field_reg - Write to the vcu reg field 2628c2ecf20Sopenharmony_ci * @iomem: vcu reg space base address 2638c2ecf20Sopenharmony_ci * @offset: vcu reg offset from base 2648c2ecf20Sopenharmony_ci * @field: vcu reg field to write to 2658c2ecf20Sopenharmony_ci * @mask: vcu reg mask 2668c2ecf20Sopenharmony_ci * @shift: vcu reg number of bits to shift the bitfield 2678c2ecf20Sopenharmony_ci */ 2688c2ecf20Sopenharmony_cistatic void xvcu_write_field_reg(void __iomem *iomem, int offset, 2698c2ecf20Sopenharmony_ci u32 field, u32 mask, int shift) 2708c2ecf20Sopenharmony_ci{ 2718c2ecf20Sopenharmony_ci u32 val = xvcu_read(iomem, offset); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci val &= ~(mask << shift); 2748c2ecf20Sopenharmony_ci val |= (field & mask) << shift; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci xvcu_write(iomem, offset, val); 2778c2ecf20Sopenharmony_ci} 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci/** 2808c2ecf20Sopenharmony_ci * xvcu_set_vcu_pll_info - Set the VCU PLL info 2818c2ecf20Sopenharmony_ci * @xvcu: Pointer to the xvcu_device structure 2828c2ecf20Sopenharmony_ci * 2838c2ecf20Sopenharmony_ci * Programming the VCU PLL based on the user configuration 2848c2ecf20Sopenharmony_ci * (ref clock freq, core clock freq, mcu clock freq). 2858c2ecf20Sopenharmony_ci * Core clock frequency has higher priority than mcu clock frequency 2868c2ecf20Sopenharmony_ci * Errors in following cases 2878c2ecf20Sopenharmony_ci * - When mcu or clock clock get from logicoreIP is 0 2888c2ecf20Sopenharmony_ci * - When VCU PLL DIV related bits value other than 1 2898c2ecf20Sopenharmony_ci * - When proper data not found for given data 2908c2ecf20Sopenharmony_ci * - When sis570_1 clocksource related operation failed 2918c2ecf20Sopenharmony_ci * 2928c2ecf20Sopenharmony_ci * Return: Returns status, either success or error+reason 2938c2ecf20Sopenharmony_ci */ 2948c2ecf20Sopenharmony_cistatic int xvcu_set_vcu_pll_info(struct xvcu_device *xvcu) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci u32 refclk, coreclk, mcuclk, inte, deci; 2978c2ecf20Sopenharmony_ci u32 divisor_mcu, divisor_core, fvco; 2988c2ecf20Sopenharmony_ci u32 clkoutdiv, vcu_pll_ctrl, pll_clk; 2998c2ecf20Sopenharmony_ci u32 cfg_val, mod, ctrl; 3008c2ecf20Sopenharmony_ci int ret, i; 3018c2ecf20Sopenharmony_ci const struct xvcu_pll_cfg *found = NULL; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci inte = xvcu_read(xvcu->logicore_reg_ba, VCU_PLL_CLK); 3048c2ecf20Sopenharmony_ci deci = xvcu_read(xvcu->logicore_reg_ba, VCU_PLL_CLK_DEC); 3058c2ecf20Sopenharmony_ci coreclk = xvcu_read(xvcu->logicore_reg_ba, VCU_CORE_CLK) * MHZ; 3068c2ecf20Sopenharmony_ci mcuclk = xvcu_read(xvcu->logicore_reg_ba, VCU_MCU_CLK) * MHZ; 3078c2ecf20Sopenharmony_ci if (!mcuclk || !coreclk) { 3088c2ecf20Sopenharmony_ci dev_err(xvcu->dev, "Invalid mcu and core clock data\n"); 3098c2ecf20Sopenharmony_ci return -EINVAL; 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci refclk = (inte * MHZ) + (deci * (MHZ / FRAC)); 3138c2ecf20Sopenharmony_ci dev_dbg(xvcu->dev, "Ref clock from logicoreIP is %uHz\n", refclk); 3148c2ecf20Sopenharmony_ci dev_dbg(xvcu->dev, "Core clock from logicoreIP is %uHz\n", coreclk); 3158c2ecf20Sopenharmony_ci dev_dbg(xvcu->dev, "Mcu clock from logicoreIP is %uHz\n", mcuclk); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci clk_disable_unprepare(xvcu->pll_ref); 3188c2ecf20Sopenharmony_ci ret = clk_set_rate(xvcu->pll_ref, refclk); 3198c2ecf20Sopenharmony_ci if (ret) 3208c2ecf20Sopenharmony_ci dev_warn(xvcu->dev, "failed to set logicoreIP refclk rate\n"); 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci ret = clk_prepare_enable(xvcu->pll_ref); 3238c2ecf20Sopenharmony_ci if (ret) { 3248c2ecf20Sopenharmony_ci dev_err(xvcu->dev, "failed to enable pll_ref clock source\n"); 3258c2ecf20Sopenharmony_ci return ret; 3268c2ecf20Sopenharmony_ci } 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci refclk = clk_get_rate(xvcu->pll_ref); 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci /* 3318c2ecf20Sopenharmony_ci * The divide-by-2 should be always enabled (==1) 3328c2ecf20Sopenharmony_ci * to meet the timing in the design. 3338c2ecf20Sopenharmony_ci * Otherwise, it's an error 3348c2ecf20Sopenharmony_ci */ 3358c2ecf20Sopenharmony_ci vcu_pll_ctrl = xvcu_read(xvcu->vcu_slcr_ba, VCU_PLL_CTRL); 3368c2ecf20Sopenharmony_ci clkoutdiv = vcu_pll_ctrl >> VCU_PLL_CTRL_CLKOUTDIV_SHIFT; 3378c2ecf20Sopenharmony_ci clkoutdiv = clkoutdiv & VCU_PLL_CTRL_CLKOUTDIV_MASK; 3388c2ecf20Sopenharmony_ci if (clkoutdiv != 1) { 3398c2ecf20Sopenharmony_ci dev_err(xvcu->dev, "clkoutdiv value is invalid\n"); 3408c2ecf20Sopenharmony_ci return -EINVAL; 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci for (i = ARRAY_SIZE(xvcu_pll_cfg) - 1; i >= 0; i--) { 3448c2ecf20Sopenharmony_ci const struct xvcu_pll_cfg *cfg = &xvcu_pll_cfg[i]; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci fvco = cfg->fbdiv * refclk; 3478c2ecf20Sopenharmony_ci if (fvco >= FVCO_MIN && fvco <= FVCO_MAX) { 3488c2ecf20Sopenharmony_ci pll_clk = fvco / VCU_PLL_DIV2; 3498c2ecf20Sopenharmony_ci if (fvco % VCU_PLL_DIV2 != 0) 3508c2ecf20Sopenharmony_ci pll_clk++; 3518c2ecf20Sopenharmony_ci mod = pll_clk % coreclk; 3528c2ecf20Sopenharmony_ci if (mod < LIMIT) { 3538c2ecf20Sopenharmony_ci divisor_core = pll_clk / coreclk; 3548c2ecf20Sopenharmony_ci } else if (coreclk - mod < LIMIT) { 3558c2ecf20Sopenharmony_ci divisor_core = pll_clk / coreclk; 3568c2ecf20Sopenharmony_ci divisor_core++; 3578c2ecf20Sopenharmony_ci } else { 3588c2ecf20Sopenharmony_ci continue; 3598c2ecf20Sopenharmony_ci } 3608c2ecf20Sopenharmony_ci if (divisor_core >= DIVISOR_MIN && 3618c2ecf20Sopenharmony_ci divisor_core <= DIVISOR_MAX) { 3628c2ecf20Sopenharmony_ci found = cfg; 3638c2ecf20Sopenharmony_ci divisor_mcu = pll_clk / mcuclk; 3648c2ecf20Sopenharmony_ci mod = pll_clk % mcuclk; 3658c2ecf20Sopenharmony_ci if (mcuclk - mod < LIMIT) 3668c2ecf20Sopenharmony_ci divisor_mcu++; 3678c2ecf20Sopenharmony_ci break; 3688c2ecf20Sopenharmony_ci } 3698c2ecf20Sopenharmony_ci } 3708c2ecf20Sopenharmony_ci } 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci if (!found) { 3738c2ecf20Sopenharmony_ci dev_err(xvcu->dev, "Invalid clock combination.\n"); 3748c2ecf20Sopenharmony_ci return -EINVAL; 3758c2ecf20Sopenharmony_ci } 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci xvcu->coreclk = pll_clk / divisor_core; 3788c2ecf20Sopenharmony_ci mcuclk = pll_clk / divisor_mcu; 3798c2ecf20Sopenharmony_ci dev_dbg(xvcu->dev, "Actual Ref clock freq is %uHz\n", refclk); 3808c2ecf20Sopenharmony_ci dev_dbg(xvcu->dev, "Actual Core clock freq is %uHz\n", xvcu->coreclk); 3818c2ecf20Sopenharmony_ci dev_dbg(xvcu->dev, "Actual Mcu clock freq is %uHz\n", mcuclk); 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci vcu_pll_ctrl &= ~(VCU_PLL_CTRL_FBDIV_MASK << VCU_PLL_CTRL_FBDIV_SHIFT); 3848c2ecf20Sopenharmony_ci vcu_pll_ctrl |= (found->fbdiv & VCU_PLL_CTRL_FBDIV_MASK) << 3858c2ecf20Sopenharmony_ci VCU_PLL_CTRL_FBDIV_SHIFT; 3868c2ecf20Sopenharmony_ci vcu_pll_ctrl &= ~(VCU_PLL_CTRL_POR_IN_MASK << 3878c2ecf20Sopenharmony_ci VCU_PLL_CTRL_POR_IN_SHIFT); 3888c2ecf20Sopenharmony_ci vcu_pll_ctrl |= (VCU_PLL_CTRL_DEFAULT & VCU_PLL_CTRL_POR_IN_MASK) << 3898c2ecf20Sopenharmony_ci VCU_PLL_CTRL_POR_IN_SHIFT; 3908c2ecf20Sopenharmony_ci vcu_pll_ctrl &= ~(VCU_PLL_CTRL_PWR_POR_MASK << 3918c2ecf20Sopenharmony_ci VCU_PLL_CTRL_PWR_POR_SHIFT); 3928c2ecf20Sopenharmony_ci vcu_pll_ctrl |= (VCU_PLL_CTRL_DEFAULT & VCU_PLL_CTRL_PWR_POR_MASK) << 3938c2ecf20Sopenharmony_ci VCU_PLL_CTRL_PWR_POR_SHIFT; 3948c2ecf20Sopenharmony_ci xvcu_write(xvcu->vcu_slcr_ba, VCU_PLL_CTRL, vcu_pll_ctrl); 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci /* Set divisor for the core and mcu clock */ 3978c2ecf20Sopenharmony_ci ctrl = xvcu_read(xvcu->vcu_slcr_ba, VCU_ENC_CORE_CTRL); 3988c2ecf20Sopenharmony_ci ctrl &= ~(VCU_PLL_DIVISOR_MASK << VCU_PLL_DIVISOR_SHIFT); 3998c2ecf20Sopenharmony_ci ctrl |= (divisor_core & VCU_PLL_DIVISOR_MASK) << 4008c2ecf20Sopenharmony_ci VCU_PLL_DIVISOR_SHIFT; 4018c2ecf20Sopenharmony_ci ctrl &= ~(VCU_SRCSEL_MASK << VCU_SRCSEL_SHIFT); 4028c2ecf20Sopenharmony_ci ctrl |= (VCU_SRCSEL_PLL & VCU_SRCSEL_MASK) << VCU_SRCSEL_SHIFT; 4038c2ecf20Sopenharmony_ci xvcu_write(xvcu->vcu_slcr_ba, VCU_ENC_CORE_CTRL, ctrl); 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci ctrl = xvcu_read(xvcu->vcu_slcr_ba, VCU_DEC_CORE_CTRL); 4068c2ecf20Sopenharmony_ci ctrl &= ~(VCU_PLL_DIVISOR_MASK << VCU_PLL_DIVISOR_SHIFT); 4078c2ecf20Sopenharmony_ci ctrl |= (divisor_core & VCU_PLL_DIVISOR_MASK) << 4088c2ecf20Sopenharmony_ci VCU_PLL_DIVISOR_SHIFT; 4098c2ecf20Sopenharmony_ci ctrl &= ~(VCU_SRCSEL_MASK << VCU_SRCSEL_SHIFT); 4108c2ecf20Sopenharmony_ci ctrl |= (VCU_SRCSEL_PLL & VCU_SRCSEL_MASK) << VCU_SRCSEL_SHIFT; 4118c2ecf20Sopenharmony_ci xvcu_write(xvcu->vcu_slcr_ba, VCU_DEC_CORE_CTRL, ctrl); 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci ctrl = xvcu_read(xvcu->vcu_slcr_ba, VCU_ENC_MCU_CTRL); 4148c2ecf20Sopenharmony_ci ctrl &= ~(VCU_PLL_DIVISOR_MASK << VCU_PLL_DIVISOR_SHIFT); 4158c2ecf20Sopenharmony_ci ctrl |= (divisor_mcu & VCU_PLL_DIVISOR_MASK) << VCU_PLL_DIVISOR_SHIFT; 4168c2ecf20Sopenharmony_ci ctrl &= ~(VCU_SRCSEL_MASK << VCU_SRCSEL_SHIFT); 4178c2ecf20Sopenharmony_ci ctrl |= (VCU_SRCSEL_PLL & VCU_SRCSEL_MASK) << VCU_SRCSEL_SHIFT; 4188c2ecf20Sopenharmony_ci xvcu_write(xvcu->vcu_slcr_ba, VCU_ENC_MCU_CTRL, ctrl); 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci ctrl = xvcu_read(xvcu->vcu_slcr_ba, VCU_DEC_MCU_CTRL); 4218c2ecf20Sopenharmony_ci ctrl &= ~(VCU_PLL_DIVISOR_MASK << VCU_PLL_DIVISOR_SHIFT); 4228c2ecf20Sopenharmony_ci ctrl |= (divisor_mcu & VCU_PLL_DIVISOR_MASK) << VCU_PLL_DIVISOR_SHIFT; 4238c2ecf20Sopenharmony_ci ctrl &= ~(VCU_SRCSEL_MASK << VCU_SRCSEL_SHIFT); 4248c2ecf20Sopenharmony_ci ctrl |= (VCU_SRCSEL_PLL & VCU_SRCSEL_MASK) << VCU_SRCSEL_SHIFT; 4258c2ecf20Sopenharmony_ci xvcu_write(xvcu->vcu_slcr_ba, VCU_DEC_MCU_CTRL, ctrl); 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci /* Set RES, CP, LFHF, LOCK_CNT and LOCK_DLY cfg values */ 4288c2ecf20Sopenharmony_ci cfg_val = (found->res << VCU_PLL_CFG_RES_SHIFT) | 4298c2ecf20Sopenharmony_ci (found->cp << VCU_PLL_CFG_CP_SHIFT) | 4308c2ecf20Sopenharmony_ci (found->lfhf << VCU_PLL_CFG_LFHF_SHIFT) | 4318c2ecf20Sopenharmony_ci (found->lock_cnt << VCU_PLL_CFG_LOCK_CNT_SHIFT) | 4328c2ecf20Sopenharmony_ci (found->lock_dly << VCU_PLL_CFG_LOCK_DLY_SHIFT); 4338c2ecf20Sopenharmony_ci xvcu_write(xvcu->vcu_slcr_ba, VCU_PLL_CFG, cfg_val); 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci return 0; 4368c2ecf20Sopenharmony_ci} 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci/** 4398c2ecf20Sopenharmony_ci * xvcu_set_pll - PLL init sequence 4408c2ecf20Sopenharmony_ci * @xvcu: Pointer to the xvcu_device structure 4418c2ecf20Sopenharmony_ci * 4428c2ecf20Sopenharmony_ci * Call the api to set the PLL info and once that is done then 4438c2ecf20Sopenharmony_ci * init the PLL sequence to make the PLL stable. 4448c2ecf20Sopenharmony_ci * 4458c2ecf20Sopenharmony_ci * Return: Returns status, either success or error+reason 4468c2ecf20Sopenharmony_ci */ 4478c2ecf20Sopenharmony_cistatic int xvcu_set_pll(struct xvcu_device *xvcu) 4488c2ecf20Sopenharmony_ci{ 4498c2ecf20Sopenharmony_ci u32 lock_status; 4508c2ecf20Sopenharmony_ci unsigned long timeout; 4518c2ecf20Sopenharmony_ci int ret; 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci ret = xvcu_set_vcu_pll_info(xvcu); 4548c2ecf20Sopenharmony_ci if (ret) { 4558c2ecf20Sopenharmony_ci dev_err(xvcu->dev, "failed to set pll info\n"); 4568c2ecf20Sopenharmony_ci return ret; 4578c2ecf20Sopenharmony_ci } 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci xvcu_write_field_reg(xvcu->vcu_slcr_ba, VCU_PLL_CTRL, 4608c2ecf20Sopenharmony_ci 1, VCU_PLL_CTRL_BYPASS_MASK, 4618c2ecf20Sopenharmony_ci VCU_PLL_CTRL_BYPASS_SHIFT); 4628c2ecf20Sopenharmony_ci xvcu_write_field_reg(xvcu->vcu_slcr_ba, VCU_PLL_CTRL, 4638c2ecf20Sopenharmony_ci 1, VCU_PLL_CTRL_RESET_MASK, 4648c2ecf20Sopenharmony_ci VCU_PLL_CTRL_RESET_SHIFT); 4658c2ecf20Sopenharmony_ci xvcu_write_field_reg(xvcu->vcu_slcr_ba, VCU_PLL_CTRL, 4668c2ecf20Sopenharmony_ci 0, VCU_PLL_CTRL_RESET_MASK, 4678c2ecf20Sopenharmony_ci VCU_PLL_CTRL_RESET_SHIFT); 4688c2ecf20Sopenharmony_ci /* 4698c2ecf20Sopenharmony_ci * Defined the timeout for the max time to wait the 4708c2ecf20Sopenharmony_ci * PLL_STATUS to be locked. 4718c2ecf20Sopenharmony_ci */ 4728c2ecf20Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(2000); 4738c2ecf20Sopenharmony_ci do { 4748c2ecf20Sopenharmony_ci lock_status = xvcu_read(xvcu->vcu_slcr_ba, VCU_PLL_STATUS); 4758c2ecf20Sopenharmony_ci if (lock_status & VCU_PLL_STATUS_LOCK_STATUS_MASK) { 4768c2ecf20Sopenharmony_ci xvcu_write_field_reg(xvcu->vcu_slcr_ba, VCU_PLL_CTRL, 4778c2ecf20Sopenharmony_ci 0, VCU_PLL_CTRL_BYPASS_MASK, 4788c2ecf20Sopenharmony_ci VCU_PLL_CTRL_BYPASS_SHIFT); 4798c2ecf20Sopenharmony_ci return 0; 4808c2ecf20Sopenharmony_ci } 4818c2ecf20Sopenharmony_ci } while (!time_after(jiffies, timeout)); 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci /* PLL is not locked even after the timeout of the 2sec */ 4848c2ecf20Sopenharmony_ci dev_err(xvcu->dev, "PLL is not locked\n"); 4858c2ecf20Sopenharmony_ci return -ETIMEDOUT; 4868c2ecf20Sopenharmony_ci} 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci/** 4898c2ecf20Sopenharmony_ci * xvcu_probe - Probe existence of the logicoreIP 4908c2ecf20Sopenharmony_ci * and initialize PLL 4918c2ecf20Sopenharmony_ci * 4928c2ecf20Sopenharmony_ci * @pdev: Pointer to the platform_device structure 4938c2ecf20Sopenharmony_ci * 4948c2ecf20Sopenharmony_ci * Return: Returns 0 on success 4958c2ecf20Sopenharmony_ci * Negative error code otherwise 4968c2ecf20Sopenharmony_ci */ 4978c2ecf20Sopenharmony_cistatic int xvcu_probe(struct platform_device *pdev) 4988c2ecf20Sopenharmony_ci{ 4998c2ecf20Sopenharmony_ci struct resource *res; 5008c2ecf20Sopenharmony_ci struct xvcu_device *xvcu; 5018c2ecf20Sopenharmony_ci int ret; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci xvcu = devm_kzalloc(&pdev->dev, sizeof(*xvcu), GFP_KERNEL); 5048c2ecf20Sopenharmony_ci if (!xvcu) 5058c2ecf20Sopenharmony_ci return -ENOMEM; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci xvcu->dev = &pdev->dev; 5088c2ecf20Sopenharmony_ci res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vcu_slcr"); 5098c2ecf20Sopenharmony_ci if (!res) { 5108c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "get vcu_slcr memory resource failed.\n"); 5118c2ecf20Sopenharmony_ci return -ENODEV; 5128c2ecf20Sopenharmony_ci } 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci xvcu->vcu_slcr_ba = devm_ioremap(&pdev->dev, res->start, 5158c2ecf20Sopenharmony_ci resource_size(res)); 5168c2ecf20Sopenharmony_ci if (!xvcu->vcu_slcr_ba) { 5178c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "vcu_slcr register mapping failed.\n"); 5188c2ecf20Sopenharmony_ci return -ENOMEM; 5198c2ecf20Sopenharmony_ci } 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "logicore"); 5228c2ecf20Sopenharmony_ci if (!res) { 5238c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "get logicore memory resource failed.\n"); 5248c2ecf20Sopenharmony_ci return -ENODEV; 5258c2ecf20Sopenharmony_ci } 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci xvcu->logicore_reg_ba = devm_ioremap(&pdev->dev, res->start, 5288c2ecf20Sopenharmony_ci resource_size(res)); 5298c2ecf20Sopenharmony_ci if (!xvcu->logicore_reg_ba) { 5308c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "logicore register mapping failed.\n"); 5318c2ecf20Sopenharmony_ci return -ENOMEM; 5328c2ecf20Sopenharmony_ci } 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci xvcu->aclk = devm_clk_get(&pdev->dev, "aclk"); 5358c2ecf20Sopenharmony_ci if (IS_ERR(xvcu->aclk)) { 5368c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Could not get aclk clock\n"); 5378c2ecf20Sopenharmony_ci return PTR_ERR(xvcu->aclk); 5388c2ecf20Sopenharmony_ci } 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci xvcu->pll_ref = devm_clk_get(&pdev->dev, "pll_ref"); 5418c2ecf20Sopenharmony_ci if (IS_ERR(xvcu->pll_ref)) { 5428c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Could not get pll_ref clock\n"); 5438c2ecf20Sopenharmony_ci return PTR_ERR(xvcu->pll_ref); 5448c2ecf20Sopenharmony_ci } 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci ret = clk_prepare_enable(xvcu->aclk); 5478c2ecf20Sopenharmony_ci if (ret) { 5488c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "aclk clock enable failed\n"); 5498c2ecf20Sopenharmony_ci return ret; 5508c2ecf20Sopenharmony_ci } 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci ret = clk_prepare_enable(xvcu->pll_ref); 5538c2ecf20Sopenharmony_ci if (ret) { 5548c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "pll_ref clock enable failed\n"); 5558c2ecf20Sopenharmony_ci goto error_aclk; 5568c2ecf20Sopenharmony_ci } 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci /* 5598c2ecf20Sopenharmony_ci * Do the Gasket isolation and put the VCU out of reset 5608c2ecf20Sopenharmony_ci * Bit 0 : Gasket isolation 5618c2ecf20Sopenharmony_ci * Bit 1 : put VCU out of reset 5628c2ecf20Sopenharmony_ci */ 5638c2ecf20Sopenharmony_ci xvcu_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, VCU_GASKET_VALUE); 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci /* Do the PLL Settings based on the ref clk,core and mcu clk freq */ 5668c2ecf20Sopenharmony_ci ret = xvcu_set_pll(xvcu); 5678c2ecf20Sopenharmony_ci if (ret) { 5688c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Failed to set the pll\n"); 5698c2ecf20Sopenharmony_ci goto error_pll_ref; 5708c2ecf20Sopenharmony_ci } 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci dev_set_drvdata(&pdev->dev, xvcu); 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "%s: Probed successfully\n", __func__); 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci return 0; 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_cierror_pll_ref: 5798c2ecf20Sopenharmony_ci clk_disable_unprepare(xvcu->pll_ref); 5808c2ecf20Sopenharmony_cierror_aclk: 5818c2ecf20Sopenharmony_ci clk_disable_unprepare(xvcu->aclk); 5828c2ecf20Sopenharmony_ci return ret; 5838c2ecf20Sopenharmony_ci} 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci/** 5868c2ecf20Sopenharmony_ci * xvcu_remove - Insert gasket isolation 5878c2ecf20Sopenharmony_ci * and disable the clock 5888c2ecf20Sopenharmony_ci * @pdev: Pointer to the platform_device structure 5898c2ecf20Sopenharmony_ci * 5908c2ecf20Sopenharmony_ci * Return: Returns 0 on success 5918c2ecf20Sopenharmony_ci * Negative error code otherwise 5928c2ecf20Sopenharmony_ci */ 5938c2ecf20Sopenharmony_cistatic int xvcu_remove(struct platform_device *pdev) 5948c2ecf20Sopenharmony_ci{ 5958c2ecf20Sopenharmony_ci struct xvcu_device *xvcu; 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci xvcu = platform_get_drvdata(pdev); 5988c2ecf20Sopenharmony_ci if (!xvcu) 5998c2ecf20Sopenharmony_ci return -ENODEV; 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci /* Add the the Gasket isolation and put the VCU in reset. */ 6028c2ecf20Sopenharmony_ci xvcu_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, 0); 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci clk_disable_unprepare(xvcu->pll_ref); 6058c2ecf20Sopenharmony_ci clk_disable_unprepare(xvcu->aclk); 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci return 0; 6088c2ecf20Sopenharmony_ci} 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_cistatic const struct of_device_id xvcu_of_id_table[] = { 6118c2ecf20Sopenharmony_ci { .compatible = "xlnx,vcu" }, 6128c2ecf20Sopenharmony_ci { .compatible = "xlnx,vcu-logicoreip-1.0" }, 6138c2ecf20Sopenharmony_ci { } 6148c2ecf20Sopenharmony_ci}; 6158c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, xvcu_of_id_table); 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_cistatic struct platform_driver xvcu_driver = { 6188c2ecf20Sopenharmony_ci .driver = { 6198c2ecf20Sopenharmony_ci .name = "xilinx-vcu", 6208c2ecf20Sopenharmony_ci .of_match_table = xvcu_of_id_table, 6218c2ecf20Sopenharmony_ci }, 6228c2ecf20Sopenharmony_ci .probe = xvcu_probe, 6238c2ecf20Sopenharmony_ci .remove = xvcu_remove, 6248c2ecf20Sopenharmony_ci}; 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_cimodule_platform_driver(xvcu_driver); 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ciMODULE_AUTHOR("Dhaval Shah <dshah@xilinx.com>"); 6298c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Xilinx VCU init Driver"); 6308c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 631