/* * Copyright (c) 2021-2026 Amlogic, Inc. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #include #include "pdd.h" #include "n200_func.h" #include "common.h" #define DRV_NAME_PREFIX "PDD: " #define PDD_CLK_DIV_MASK GENMASK(7, 0) #define PDD_CLK_DIV_SHIFT (0) #define PDD_CLK_GATE BIT(8) #define PDD_CLK_MUX_MASK GENMASK(10, 9) #define FLT_TICK_BIT_WIDTH 2 #define FLT_CNT_BIT_WIDTH 3 #define FLT_TICK_MASK(OFFSET) ((BIT(FLT_TICK_BIT_WIDTH) - 1) << (OFFSET)) #define FLT_CNT_MASK(OFFSET) ((BIT(FLT_CNT_BIT_WIDTH) - 1) << (OFFSET)) #define DET_TRIM_BIT_WIDTH 6 #define DET_CTRL_BIT_WIDTH 2 #define DET_TRIM_MASK(OFFSET) ((BIT(DET_TRIM_BIT_WIDTH) - 1) << (OFFSET)) #define DET_CTRL_MASK(OFFSET) ((BIT(DET_CTRL_BIT_WIDTH) - 1) << (OFFSET)) static uint32_t PddRegBackup[7]; static void (*handler)(void); static void prvPddIrqHandler(void) { if (REG32(PDD_REG_BASE + PDD_IRQ_OUT_REG_OFFS) & BIT(PDD_IRQ_OUT_BIT_OFFS)) handler(); /* Clear PDD IRQ */ REG32_UPDATE_BITS(PDD_REG_BASE + PDD_IRQ_CLR_REG_OFFS, BIT(PDD_IRQ_CLR_BIT_OFFS), BIT(PDD_IRQ_CLR_BIT_OFFS)); } void vPddInit(enum PddTriggerLevel level, void (*callback)(void)) { uint32_t mask; uint32_t value; handler = callback; /* Clock Init: 3M=24M/(0x7 + 1) */ PddRegBackup[0] = REG32(PDD_CLK_BASE); REG32_UPDATE_BITS(PDD_CLK_BASE, PDD_CLK_DIV_MASK, 0x7 << PDD_CLK_DIV_SHIFT); REG32_UPDATE_BITS(PDD_CLK_BASE, PDD_CLK_GATE, PDD_CLK_GATE); /* Sys Clock Enable */ PddRegBackup[1] = REG32(PDD_SYS_CLK_EN_BASE); REG32(PDD_SYS_CLK_EN_BASE) |= BIT(PDD_SYS_CLK_EN_BIT); /* Set Trigger Level */ PddRegBackup[2] = REG32(PDD_REG_BASE + PDD_DET_CTRL_REG_OFFS); mask = DET_CTRL_MASK(PDD_DET_CTRL_BIT_OFFS); value = (uint32_t)level << PDD_DET_CTRL_BIT_OFFS; REG32_UPDATE_BITS(PDD_REG_BASE + PDD_DET_CTRL_REG_OFFS, mask, value); /* * filter_tick_sel: * 2'b00: 1us/tick * 2'b01: 10us/tick * 2'b10: 100us/tick * 2'b11: 1ms/tick */ PddRegBackup[3] = REG32(PDD_REG_BASE + PDD_FLT_TICK_REG_OFFS); mask = FLT_TICK_MASK(PDD_FLT_TICK_BIT_OFFS); value = 1 << PDD_FLT_TICK_BIT_OFFS; /* Select 10us/tick */ REG32_UPDATE_BITS(PDD_REG_BASE + PDD_FLT_TICK_REG_OFFS, mask, value); /* * filter_cnt_sel: * 3'b000: 0 tick (no filter) * 3'b001: 1x3 tick * 3'b010: 2x3 tick * ... */ PddRegBackup[4] = REG32(PDD_REG_BASE + PDD_FLT_CNT_REG_OFFS); mask = FLT_CNT_MASK(PDD_FLT_CNT_BIT_OFFS); value = 0x7 << PDD_FLT_CNT_BIT_OFFS; /* Select 7x3 tick */ REG32_UPDATE_BITS(PDD_REG_BASE + PDD_FLT_CNT_REG_OFFS, mask, value); /* Enable Detection */ PddRegBackup[5] = REG32(PDD_REG_BASE + PDD_DET_EN_REG_OFFS); REG32_UPDATE_BITS(PDD_REG_BASE + PDD_DET_EN_REG_OFFS, BIT(PDD_DET_EN_BIT_OFFS), BIT(PDD_DET_EN_BIT_OFFS)); /* Clear PDD IRQ */ REG32_UPDATE_BITS(PDD_REG_BASE + PDD_IRQ_CLR_REG_OFFS, BIT(PDD_IRQ_CLR_BIT_OFFS), BIT(PDD_IRQ_CLR_BIT_OFFS)); /* Enable PDD IRQ */ PddRegBackup[6] = REG32(PDD_REG_BASE + PDD_IRQ_EN_REG_OFFS); REG32_UPDATE_BITS(PDD_REG_BASE + PDD_IRQ_EN_REG_OFFS, BIT(PDD_IRQ_EN_BIT_OFFS), BIT(PDD_IRQ_EN_BIT_OFFS)); /* Interrupt Init */ RegisterIrq(PDD_INTERRUPT_NUM, 1, prvPddIrqHandler); EnableIrq(PDD_INTERRUPT_NUM); printf(DRV_NAME_PREFIX "EN\n"); } void vPddDeinit(void) { DisableIrq(PDD_INTERRUPT_NUM); UnRegisterIrq(PDD_INTERRUPT_NUM); REG32(PDD_REG_BASE + PDD_IRQ_EN_REG_OFFS) = PddRegBackup[6]; REG32(PDD_REG_BASE + PDD_DET_EN_REG_OFFS) = PddRegBackup[5]; REG32(PDD_REG_BASE + PDD_FLT_CNT_REG_OFFS) = PddRegBackup[4]; REG32(PDD_REG_BASE + PDD_FLT_TICK_REG_OFFS) = PddRegBackup[3]; REG32(PDD_REG_BASE + PDD_DET_CTRL_REG_OFFS) = PddRegBackup[2]; REG32(PDD_SYS_CLK_EN_BASE) = PddRegBackup[1]; REG32(PDD_CLK_BASE) = PddRegBackup[0]; printf(DRV_NAME_PREFIX "DIS\n"); }