pi1541/rpiHardware.h

207 lines
7.2 KiB
C
Raw Normal View History

2018-05-20 04:53:34 +00:00
// Pi1541 - A Commodore 1541 disk drive emulator
// Copyright(C) 2018 Stephen White
//
// This file is part of Pi1541.
//
// Pi1541 is free software : you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Pi1541 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Pi1541. If not, see <http://www.gnu.org/licenses/>.
#ifndef RPIHARDWARE_H
#define RPIHARDWARE_H
#include <stdio.h>
#include "types.h"
#include "rpi-gpio.h"
#include "debug.h"
#define DMA_ENABLE (PERIPHERAL_BASE + 0x7FF0) // Global Enable bits for each DMA Channel
#define DMA0_BASE (PERIPHERAL_BASE + 0x7000) // DMA Channel 0 Register Set
#define DMA_CONBLK_AD 4 // DMA Channel 0..14 Control Block Address
#define DMA_CS 0 // DMA Channel 0..14 Control & Status
#define DMA_ACTIVE 1
#define DMA_END 2
#define DMA_DEST_DREQ 0x40
#define DMA_SRC_INC 0x100
#define DMA_PERMAP_5 0x50000
#define ARM_GPIO_GPFSEL0 (RPI_GPIO_BASE + 0x00)
#define ARM_GPIO_GPFSEL1 (RPI_GPIO_BASE + 0x04)
#define ARM_GPIO_GPFSEL4 (RPI_GPIO_BASE + 0x10)
#define ARM_GPIO_GPSET0 (RPI_GPIO_BASE + 0x1C)
#define ARM_GPIO_GPCLR0 (RPI_GPIO_BASE + 0x28)
#define ARM_GPIO_GPLEV0 (RPI_GPIO_BASE + 0x34)
#define ARM_GPIO_GPEDS0 (RPI_GPIO_BASE + 0x40)
#define ARM_GPIO_GPREN0 (RPI_GPIO_BASE + 0x4C)
#define ARM_GPIO_GPFEN0 (RPI_GPIO_BASE + 0x58)
#define ARM_GPIO_GPHEN0 (RPI_GPIO_BASE + 0x64)
#define ARM_GPIO_GPLEN0 (RPI_GPIO_BASE + 0x70)
#define ARM_GPIO_GPAREN0 (RPI_GPIO_BASE + 0x7C)
#define ARM_GPIO_GPAFEN0 (RPI_GPIO_BASE + 0x88)
#define ARM_GPIO_GPPUD (RPI_GPIO_BASE + 0x94)
#define ARM_GPIO_GPPUDCLK0 (RPI_GPIO_BASE + 0x98)
#define ARM_SYSTIMER_BASE (PERIPHERAL_BASE + 0x3000)
#define ARM_SYSTIMER_CS (ARM_SYSTIMER_BASE + 0x00)
#define ARM_SYSTIMER_CLO (ARM_SYSTIMER_BASE + 0x04)
#define ARM_SYSTIMER_CHI (ARM_SYSTIMER_BASE + 0x08)
#define ARM_SYSTIMER_C0 (ARM_SYSTIMER_BASE + 0x0C)
#define ARM_SYSTIMER_C1 (ARM_SYSTIMER_BASE + 0x10)
#define ARM_SYSTIMER_C2 (ARM_SYSTIMER_BASE + 0x14)
#define ARM_SYSTIMER_C3 (ARM_SYSTIMER_BASE + 0x18)
// External Mass Media Controller (SD Card)
#define ARM_EMMC_BASE (PERIPHERAL_BASE + 0x300000)
#define DEVICE_ID_SD_CARD 0
#define DEVICE_ID_USB_HCD 3
#define POWER_STATE_OFF (0 << 0)
#define POWER_STATE_ON (1 << 0)
#define POWER_STATE_WAIT (1 << 1)
#define POWER_STATE_DEVICE_DOESNT_EXIST (1 << 1) // in response
#define CLOCK_ID_EMMC 1
#define CLOCK_ID_UART 2
#define CLOCK_ID_CORE 4
#define CM_BASE (PERIPHERAL_BASE + 0x101000)
#define CM_PWMCTL (CM_BASE + 0xA0) // Clock Manager PWM Clock Control
#define CM_PWMDIV (CM_BASE + 0xA4) // Clock Manager PWM Clock Divisor
#define CM_PASSWORD 0x5A000000 // Clock Control Password "5A"
#define CM_SRC_OSCILLATOR 0x01
#define CM_ENAB 0x10 // Enable The Clock Generator
#define PWM_BASE (PERIPHERAL_BASE + 0x20C000)
#define PWM_CTL (PWM_BASE + 0x0)
#define PWM_STATUS (PWM_BASE + 0x4)
#define PWM_DMAC (PWM_BASE + 0x8)
#define PWM_RNG1 (PWM_BASE + 0x10)
#define PWM_FIF1 (PWM_BASE + 0x18) // PWM FIFO Input
#define PWM_RNG2 (PWM_BASE + 0x20)
#define PWM_ENAB 0x80000000 // PWM DMA Configuration DMA Enable
#define PWM_PWEN1 0x1 // Channel 1 Enable
#define PWM_MODE1 0x2 // Channel 1 Mode
#define PWM_RPTL1 0x4 // Channel 1 Repeat Last Data
#define PWM_SBIT1 0x8 // Channel 1 Silence Bit
#define PWM_POLA1 0x10 // Channel 1 Polarity
#define PWM_USEF1 0x20 // Channel 1 Use Fifo
#define PWM_CLRF1 0x40 // Clear Fifo
#define PWM_MSEN1 0x80 // Channel 1 M / S Enable
#define PWM_PWEN2 0x100 // Channel 2 Enable
#define PWM_MODE2 0x200 // Channel 2 Mode
#define PWM_RPTL2 0x400 // Channel 2 Repeat Last Data
#define PWM_SBIT2 0x800 // Channel 2 Silence Bit
#define PWM_POLA2 0x1000 // Channel 2 Polarity
#define PWM_USEF2 0x2000 // Channel 2 Use Fifo
#define PWM_MSEN2 0x8000 // Channel 2 M / S Enable
// PWM Status flags
#define PWM_FULL1 0x1
#define PWM_EMPT1 0x2
//
// Interrupt Controller
//
#define ARM_IC_BASE (PERIPHERAL_BASE + 0xB000)
#define ARM_IC_IRQ_BASIC_PENDING (ARM_IC_BASE + 0x200)
#define ARM_IC_IRQ_PENDING_1 (ARM_IC_BASE + 0x204)
#define ARM_IC_IRQ_PENDING_2 (ARM_IC_BASE + 0x208)
#define ARM_IC_FIQ_CONTROL (ARM_IC_BASE + 0x20C)
#define ARM_IC_ENABLE_IRQS_1 (ARM_IC_BASE + 0x210)
#define ARM_IC_ENABLE_IRQS_2 (ARM_IC_BASE + 0x214)
#define ARM_IC_ENABLE_BASIC_IRQS (ARM_IC_BASE + 0x218)
#define ARM_IC_DISABLE_IRQS_1 (ARM_IC_BASE + 0x21C)
#define ARM_IC_DISABLE_IRQS_2 (ARM_IC_BASE + 0x220)
#define ARM_IC_DISABLE_BASIC_IRQS (ARM_IC_BASE + 0x224)
#ifdef __cplusplus
extern "C" {
#endif
#include "rpi-mailbox-interface.h"
static inline u32 read32(unsigned int nAddress)
{
return *(u32 volatile *)nAddress;
}
static inline void write32(unsigned int nAddress, u32 nValue)
{
*(u32 volatile *)nAddress = nValue;
}
static inline void delay_us(u32 amount)
{
u32 count;
for (count = 0; count < amount; ++count)
{
unsigned before;
unsigned after;
// We try to update every micro second and use as a rough timer to count micro seconds
before = read32(ARM_SYSTIMER_CLO);
do
{
after = read32(ARM_SYSTIMER_CLO);
} while (after == before);
}
}
static inline int get_clock_rate(int clk_id)
{
rpi_mailbox_property_t *buf;
RPI_PropertyInit();
RPI_PropertyAddTag(TAG_GET_CLOCK_RATE, clk_id);
RPI_PropertyProcess();
buf = RPI_PropertyGet(TAG_GET_CLOCK_RATE);
if (buf)
return buf->data.buffer_32[1];
else
return 0;
}
#ifdef __cplusplus
}
#endif
//DMB - whenever a memory access requires ordering with regards to another memory access.
//DSB - whenever a memory access needs to have completed before program execution progresses.
//ISB - whenever instruction fetches need to explicitly take place after a certain point in the program, for example after memory map updates or after writing code to be executed. (In practice, this means "throw away any prefetched instructions at this point".)
//DMB - It prevents reordering of data accesses instructions across itself. All data accesses by this processor / core before the DMB will be visible to all other masters within the specified shareability domain before any of the data accesses after it.
// It also ensures that any explicit preceding data(or unified) cache maintenance operations have completed before any subsequent data accesses are executed.
#if defined(RPI2) || defined(RPI3)
#define DataSyncBarrier() asm volatile ("dsb" ::: "memory")
#define DataMemBarrier() asm volatile ("dmb" ::: "memory")
#define InstructionSyncBarrier() __asm volatile ("isb" ::: "memory")
#define InstructionMemBarrier() __asm volatile ("isb" ::: "memory")
#else
#define DataSyncBarrier() asm volatile ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0) : "memory")
#define DataMemBarrier() asm volatile ("mcr p15, 0, %0, c7, c10, 5" : : "r" (0) : "memory")
#define FlushPrefetchBuffer() __asm volatile ("mcr p15, 0, %0, c7, c5, 4" : : "r" (0) : "memory")
#define InstructionSyncBarrier() FlushPrefetchBuffer()
#define InstructionMemBarrier() FlushPrefetchBuffer()
#endif
#endif