Newer
Older
mbed-os / targets / TARGET_Cypress / TARGET_PSOC6 / mtb-pdl-cat1 / drivers / source / ppu_v1.c
@Dustin Crossman Dustin Crossman on 4 Jun 2021 9 KB Fix file modes.
/***************************************************************************//**
* \file ppu_v1.c
* \version 1.0
*
* This file provides the source code for ARM PPU driver
*
********************************************************************************
* \copyright
* Copyright 2016-2020 Cypress Semiconductor Corporation
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/

#include "cy_device.h"

#if defined (CY_IP_MXS28SRSS)

#include <stddef.h>
#include <ppu_v1.h>

void ppu_v1_init(struct ppu_v1_reg *ppu)
{
    CY_ASSERT(ppu != NULL);

    /* Set edge sensitivity to masked for all input edges */
    ppu->IESR = 0;

    /* Mask all interrupts */
    ppu->IMR = PPU_V1_IMR_MASK;

    /* Acknowledge any interrupt left pending */
    ppu->ISR = PPU_V1_ISR_MASK;
}

/*
 * PWPR and PWSR registers
 */
int ppu_v1_request_power_mode(struct ppu_v1_reg *ppu, enum ppu_v1_mode ppu_mode)
{
    uint32_t power_policy;
    CY_ASSERT(ppu != NULL);
    CY_ASSERT(ppu_mode < PPU_V1_MODE_COUNT);

    power_policy = ppu->PWPR & ~(PPU_V1_PWPR_POLICY | PPU_V1_PWPR_DYNAMIC_EN);
    ppu->PWPR = power_policy | ppu_mode;

    return CY_RET_SUCCESS;
}

int ppu_v1_set_power_mode(struct ppu_v1_reg *ppu, enum ppu_v1_mode ppu_mode)
{
    int status;

    status = ppu_v1_request_power_mode(ppu, ppu_mode);
    if (status != CY_RET_SUCCESS)
        return status;

    while ((ppu->PWSR & (PPU_V1_PWSR_PWR_STATUS | PPU_V1_PWSR_PWR_DYN_STATUS))
            != ppu_mode)
        continue;

    return CY_RET_SUCCESS;
}

int ppu_v1_request_operating_mode(struct ppu_v1_reg *ppu,
                                  enum ppu_v1_opmode op_mode)
{
    uint32_t power_policy;
    CY_ASSERT(ppu != NULL);
    CY_ASSERT(op_mode < PPU_V1_OPMODE_COUNT);

    power_policy = ppu->PWPR & ~(PPU_V1_PWPR_OP_POLICY | PPU_V1_PWPR_OP_DYN_EN);
    ppu->PWPR = power_policy | (op_mode << PPU_V1_PWPR_OP_POLICY_POS);

    return CY_RET_SUCCESS;
}

void ppu_v1_opmode_dynamic_enable(struct ppu_v1_reg *ppu,
                                  enum ppu_v1_opmode min_dyn_mode)
{
    uint32_t power_policy;

    CY_ASSERT(ppu != NULL);
    CY_ASSERT(min_dyn_mode < PPU_V1_OPMODE_COUNT);

    power_policy = ppu->PWPR & ~PPU_V1_PWPR_OP_POLICY;
    ppu->PWPR = power_policy |
                PPU_V1_PWPR_OP_DYN_EN |
                (min_dyn_mode << PPU_V1_PWPR_OP_POLICY_POS);
    while ((ppu->PWSR & PPU_V1_PWSR_OP_DYN_STATUS) == 0)
        continue;
}

void ppu_v1_dynamic_enable(struct ppu_v1_reg *ppu,
                           enum ppu_v1_mode min_dyn_state)
{
    uint32_t power_policy;

    CY_ASSERT(ppu != NULL);
    CY_ASSERT(min_dyn_state < PPU_V1_MODE_COUNT);

    power_policy = ppu->PWPR & ~PPU_V1_PWPR_POLICY;
    ppu->PWPR = power_policy | PPU_V1_PWPR_DYNAMIC_EN | min_dyn_state;
    while ((ppu->PWSR & PPU_V1_PWSR_PWR_DYN_STATUS) == 0)
        continue;
}

void ppu_v1_lock_off_enable(struct ppu_v1_reg *ppu)
{
    CY_ASSERT(ppu != NULL);

    ppu->PWPR |= PPU_V1_PWPR_OFF_LOCK_EN;
}

void ppu_v1_lock_off_disable(struct ppu_v1_reg *ppu)
{
    CY_ASSERT(ppu != NULL);

    ppu->PWPR &= ~PPU_V1_PWPR_OFF_LOCK_EN;
}

enum ppu_v1_mode ppu_v1_get_power_mode(struct ppu_v1_reg *ppu)
{
    CY_ASSERT(ppu != NULL);

    return (enum ppu_v1_mode)(ppu->PWSR & PPU_V1_PWSR_PWR_STATUS);
}

enum ppu_v1_mode ppu_v1_get_programmed_power_mode(struct ppu_v1_reg *ppu)
{
    CY_ASSERT(ppu != NULL);

    return (enum ppu_v1_mode)(ppu->PWPR & PPU_V1_PWPR_POLICY);
}

enum ppu_v1_opmode ppu_v1_get_operating_mode(struct ppu_v1_reg *ppu)
{
    CY_ASSERT(ppu != NULL);

    return (enum ppu_v1_opmode)
        ((ppu->PWSR & PPU_V1_PWSR_OP_STATUS) >> PPU_V1_PWSR_OP_STATUS_POS);
}

enum ppu_v1_opmode ppu_v1_get_programmed_operating_mode(struct ppu_v1_reg *ppu)
{
    CY_ASSERT(ppu != NULL);

    return (enum ppu_v1_opmode)
        ((ppu->PWPR & PPU_V1_PWPR_OP_POLICY) >> PPU_V1_PWPR_OP_POLICY_POS);
}

bool ppu_v1_is_dynamic_enabled(struct ppu_v1_reg *ppu)
{
    CY_ASSERT(ppu != NULL);

    return ((ppu->PWSR & PPU_V1_PWSR_PWR_DYN_STATUS) != 0);
}

bool ppu_v1_is_locked(struct ppu_v1_reg *ppu)
{
    CY_ASSERT(ppu != NULL);

    return ((ppu->PWSR & PPU_V1_PWSR_OFF_LOCK_STATUS) != 0);
}

/*
 * DISR register
 */
bool ppu_v1_is_power_devactive_high(struct ppu_v1_reg *ppu,
                                    enum ppu_v1_mode ppu_mode)
{
    CY_ASSERT(ppu != NULL);

    return (ppu->DISR &
            (1 << (ppu_mode + PPU_V1_DISR_PWR_DEVACTIVE_STATUS_POS))) != 0;
}

bool ppu_v1_is_op_devactive_high(struct ppu_v1_reg *ppu,
                                 enum ppu_v1_op_devactive op_devactive)
{
    CY_ASSERT(ppu != NULL);

    return (ppu->DISR &
            (1 << (op_devactive + PPU_V1_DISR_OP_DEVACTIVE_STATUS_POS))) != 0;
}

/*
 * UNLK register
 */
void ppu_v1_off_unlock(struct ppu_v1_reg *ppu)
{
    CY_ASSERT(ppu != NULL);

    ppu->UNLK = PPU_V1_UNLK_OFF_UNLOCK;
}

/*
 * PWCR register
 */
void ppu_v1_disable_devactive(struct ppu_v1_reg *ppu)
{
    CY_ASSERT(ppu != NULL);

    ppu->PWCR &= ~PPU_V1_PWCR_DEV_ACTIVE_EN;
}

void ppu_v1_disable_handshake(struct ppu_v1_reg *ppu)
{
    CY_ASSERT(ppu != NULL);

    ppu->PWCR &= ~PPU_V1_PWCR_DEV_REQ_EN;
}

/*
 * Interrupt registers: IMR, AIMR, ISR, AISR, IESR, OPSR
 */
void ppu_v1_interrupt_mask(struct ppu_v1_reg *ppu, unsigned int mask)
{
    CY_ASSERT(ppu != NULL);

    ppu->IMR |= mask & PPU_V1_IMR_MASK;
}

void ppu_v1_additional_interrupt_mask(struct ppu_v1_reg *ppu, unsigned int mask)
{
    CY_ASSERT(ppu != NULL);

    ppu->AIMR |= mask & PPU_V1_AIMR_MASK;
}

void ppu_v1_interrupt_unmask(struct ppu_v1_reg *ppu, unsigned int mask)
{
    CY_ASSERT(ppu != NULL);

    ppu->IMR &= ~(mask & PPU_V1_IMR_MASK);
}

void ppu_v1_additional_interrupt_unmask(struct ppu_v1_reg *ppu,
    unsigned int mask)
{
    CY_ASSERT(ppu != NULL);

    ppu->AIMR &= ~(mask & PPU_V1_AIMR_MASK);
}

bool ppu_v1_is_additional_interrupt_pending(struct ppu_v1_reg *ppu,
    unsigned int mask)
{
    return (ppu->AISR & (mask & PPU_V1_AISR_MASK)) != 0;
}

void ppu_v1_ack_interrupt(struct ppu_v1_reg *ppu, unsigned int mask)
{
    CY_ASSERT(ppu != NULL);

    ppu->ISR &= mask & PPU_V1_IMR_MASK;
}

void ppu_v1_ack_additional_interrupt(struct ppu_v1_reg *ppu, unsigned int mask)
{
    CY_ASSERT(ppu != NULL);

    ppu->AISR &= mask & PPU_V1_AIMR_MASK;
}

void ppu_v1_set_input_edge_sensitivity(struct ppu_v1_reg *ppu,
    enum ppu_v1_mode ppu_mode, enum ppu_v1_edge_sensitivity edge_sensitivity)
{
    CY_ASSERT(ppu != NULL);
    CY_ASSERT(ppu_mode < PPU_V1_MODE_COUNT);
    CY_ASSERT((edge_sensitivity & ~PPU_V1_EDGE_SENSITIVITY_MASK) == 0);

    /* Clear current settings */
    ppu->IESR &= ~(PPU_V1_EDGE_SENSITIVITY_MASK <<
                   (ppu_mode * PPU_V1_BITS_PER_EDGE_SENSITIVITY));

    /* Update settings */
    ppu->IESR |= edge_sensitivity <<
                 (ppu_mode * PPU_V1_BITS_PER_EDGE_SENSITIVITY);
}

enum ppu_v1_edge_sensitivity ppu_v1_get_input_edge_sensitivity(
    struct ppu_v1_reg *ppu, enum ppu_v1_mode ppu_mode)
{
    CY_ASSERT(ppu != NULL);
    CY_ASSERT(ppu_mode < PPU_V1_MODE_COUNT);

    return (enum ppu_v1_edge_sensitivity)(
            (ppu->IESR >> (ppu_mode * PPU_V1_BITS_PER_EDGE_SENSITIVITY)) &
            PPU_V1_EDGE_SENSITIVITY_MASK);
}

void ppu_v1_ack_power_active_edge_interrupt(struct ppu_v1_reg *ppu,
    enum ppu_v1_mode ppu_mode)
{
    ppu->ISR = 1 << (ppu_mode + PPU_V1_ISR_ACTIVE_EDGE_POS);
}

bool ppu_v1_is_power_active_edge_interrupt(struct ppu_v1_reg *ppu,
    enum ppu_v1_mode ppu_mode)
{
    return ppu->ISR & (1 << (ppu_mode + PPU_V1_ISR_ACTIVE_EDGE_POS));
}

void ppu_v1_set_op_active_edge_sensitivity(struct ppu_v1_reg *ppu,
    enum ppu_v1_op_devactive op_devactive,
    enum ppu_v1_edge_sensitivity edge_sensitivity)
{
    CY_ASSERT(ppu != NULL);
    CY_ASSERT(op_devactive < PPU_V1_OP_DEVACTIVE_COUNT);
    CY_ASSERT((edge_sensitivity & ~PPU_V1_EDGE_SENSITIVITY_MASK) == 0);

    /* Clear current settings */
    ppu->OPSR &= ~(PPU_V1_EDGE_SENSITIVITY_MASK <<
                   (op_devactive * PPU_V1_BITS_PER_EDGE_SENSITIVITY));

    /* Update settings */
    ppu->OPSR |= edge_sensitivity <<
                 (op_devactive * PPU_V1_BITS_PER_EDGE_SENSITIVITY);
}

enum ppu_v1_edge_sensitivity ppu_v1_get_op_active_edge_sensitivity(
    struct ppu_v1_reg *ppu, enum ppu_v1_op_devactive op_devactive)
{
    CY_ASSERT(ppu != NULL);
    CY_ASSERT(op_devactive < PPU_V1_OP_DEVACTIVE_COUNT);

    return (enum ppu_v1_edge_sensitivity)(
            (ppu->OPSR >> (op_devactive * PPU_V1_BITS_PER_EDGE_SENSITIVITY)) &
            PPU_V1_EDGE_SENSITIVITY_MASK);
}

void ppu_v1_ack_op_active_edge_interrupt(struct ppu_v1_reg *ppu,
    enum ppu_v1_op_devactive op_devactive)
{
    ppu->ISR = 1 << (op_devactive + PPU_V1_ISR_OP_ACTIVE_EDGE_POS);
}

bool ppu_v1_is_op_active_edge_interrupt(struct ppu_v1_reg *ppu,
    enum ppu_v1_op_devactive op_devactive)
{
    return ppu->ISR & (1 << (op_devactive + PPU_V1_ISR_OP_ACTIVE_EDGE_POS));
}

bool ppu_v1_is_dyn_policy_min_interrupt(struct ppu_v1_reg *ppu)
{
    return ppu->ISR & PPU_V1_ISR_DYN_POLICY_MIN_IRQ;
}

/*
 * IDR0 register
 */
unsigned int ppu_v1_get_num_opmode(struct ppu_v1_reg *ppu)
{
    return ((ppu->IDR0 & PPU_V1_IDR0_NUM_OPMODE)
            >> PPU_V1_IDR0_NUM_OPMODE_POS) + 1;
}

/*
 * AIDR register
 */
unsigned int ppu_v1_get_arch_id(struct ppu_v1_reg *ppu)
{
    CY_ASSERT(ppu != NULL);

    return (ppu->AIDR & (PPU_V1_AIDR_ARCH_REV_MINOR |
                         PPU_V1_AIDR_ARCH_REV_MAJOR));
}
#endif /* CY_IP_MXS28SRSS */