131 lines
3.7 KiB
C
131 lines
3.7 KiB
C
/*
|
|
* Copyright (c) 2021-2026 Amlogic, Inc. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
#include <unistd.h>
|
|
#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");
|
|
}
|