Add initial support for Olimex iMX233 based OLinuXino boards.

https://www.olimex.com/Products/OLinuXino/iMX233/
Contributed by Petri Laakso.
This commit is contained in:
jkunz 2012-11-20 19:08:45 +00:00
parent eba5cacbdb
commit da8587eaed
17 changed files with 2705 additions and 2 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: md.evbarm,v 1.11 2012/11/15 19:49:11 jkunz Exp $
# $NetBSD: md.evbarm,v 1.12 2012/11/20 19:09:47 jkunz Exp $
./usr/mdec/gzboot_ADI_BRH_0x00140000.bin base-sysutil-bin
./usr/mdec/gzboot_GEMINI_0x01600000.bin base-sysutil-bin
./usr/mdec/gzboot_IQ80310_0x00080000.bin base-sysutil-bin
@ -8,6 +8,7 @@
./usr/mdec/gzboot_SMDK2800_0x00100000.bin base-sysutil-bin
./usr/mdec/gzboot_TS7200_0x60660000.bin base-sysutil-bin
./usr/mdec/bootmini2440 base-sysutil-bin
./usr/mdec/bootimx23 base-sysutil-bin
./usr/sbin/elftosb base-sysutil-bin
./usr/sbin/sbtool base-sysutil-bin
./usr/sbin/sbkeygen base-sysutil-bin

View File

@ -0,0 +1,57 @@
# $Id: IMX23_OLINUXINO,v 1.1 2012/11/20 19:08:45 jkunz Exp $
#
# IMX23_OLINUXINO -- Olimex i.MX23 OLinuXino kernel configuration file.
#
include "arch/evbarm/conf/std.imx23_olinuxino"
maxusers 8
config netbsd root on ? type ?
# The main bus device
mainbus0 at root
# The boot CPU
cpu0 at mainbus?
# APBH bus
apbh0 at mainbus? base 0x80000000 size 0x00040000
# APBH DMA
#apbdma0 at apbh? addr 0x80004000 size 0x2000 irq -1
# Interrupt controller
icoll0 at apbh? addr 0x80000000 size 0x2000 irq -1
# Synchronous serial port for SD/MMC
#ssp0 at apbh? addr 0x80010000 size 0x2000 irq 15
#sdmmc* at ssp?
#ld* at sdmmc?
# APBX bus
apbx0 at mainbus? base 0x80040000 size 0x00040000
# APBX DMA
#apbdma1 at apbx? addr 0x80024000 size 0x2000 irq -1
# Timers and rotary decoder
timrot0 at apbx? addr 0x80068020 size 0x20 irq 28
timrot1 at apbx? addr 0x80068040 size 0x20 irq 29
#timrot2 at apbx? addr 0x80068060 size 0x20 irq 30
#timrot3 at apbx? addr 0x80068080 size 0x20 irq 31
plcom0 at apbx? addr 0x80070000 size 0x1000 irq 0
options MEMSIZE=64
options DDB
options HZ=100
options MEMORY_DISK_HOOKS
options MEMORY_DISK_IS_ROOT
options MEMORY_DISK_ROOT_SIZE=12288 # 6 megs
options MEMORY_DISK_RBFLAGS=RB_SINGLE
pseudo-device md
file-system FFS

View File

@ -0,0 +1,10 @@
# $Id: files.imx23_olinuxino,v 1.1 2012/11/20 19:08:45 jkunz Exp $
#
# Olimex i.MX23 OLinuXino board configuration info.
#
# Pull in SoC support
include "arch/arm/imx/files.imx23"
file arch/evbarm/imx23_olinuxino/imx23_olinuxino_machdep.c

View File

@ -0,0 +1,7 @@
# $Id: mk.imx23_olinuxino,v 1.1 2012/11/20 19:08:45 jkunz Exp $
SYSTEM_FIRST_OBJ= imx23_olinuxino_start.o
SYSTEM_FIRST_SFILE= ${THISARM}/imx23_olinuxino/imx23_olinuxino_start.S
KERNEL_BASE_PHYS=0x40000000
KERNEL_BASE_VIRT=0x40000000

View File

@ -0,0 +1,21 @@
# $Id: std.imx23_olinuxino,v 1.1 2012/11/20 19:08:45 jkunz Exp $
#
# IMX23_OLINUXINO standard kernel options.
machine evbarm arm
include "conf/std" # Standard MI options.
include "arch/arm/conf/std.arm" # Standard NetBSD/arm options.
options EXEC_ELF32
options CPU_ARM9E
# To support easy transit to ../arch/arm/arm32
options ARM32
options ARM_INTR_IMPL="<arch/arm/imx/imx23_intr.h>"
options EVBARM_BOARDTYPE=OLinuXino
options KERNEL_BASE_EXT=0x40000000
makeoptions BOARDMKFRAG="${THISARM}/conf/mk.imx23_olinuxino"
makeoptions CPUFLAGS="-march=armv5te -mtune=arm926ej-s"
include "arch/evbarm/conf/files.imx23_olinuxino"

View File

@ -0,0 +1,679 @@
/* $Id: imx23_olinuxino_machdep.c,v 1.1 2012/11/20 19:08:45 jkunz Exp $ */
/*
* Copyright (c) 2012 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Petri Laakso.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/bus.h>
#include <sys/cdefs.h>
#include <sys/device.h>
#include <sys/lwp.h>
#include <sys/mount.h>
#include <sys/mutex.h>
#include <sys/param.h>
#include <sys/reboot.h>
#include <sys/rnd.h>
#include <sys/termios.h>
#include <sys/types.h>
#include <uvm/uvm.h>
#include <uvm/uvm_prot.h>
#include <uvm/uvm_pmap.h>
#include <machine/db_machdep.h>
#include <machine/bootconfig.h>
#include <machine/frame.h>
#include <machine/param.h>
#include <machine/pcb.h>
#include <machine/pmap.h>
#include <arm/undefined.h>
#include <arm/arm32/machdep.h>
#include <arm/imx/imx23_digctlreg.h>
#include <arm/imx/imx23_clkctrlreg.h>
#include <arm/imx/imx23_rtcreg.h>
#include <arm/imx/imx23_uartdbgreg.h>
#include <arm/imx/imx23var.h>
#include "plcom.h"
#if (NPLCOM > 0)
#include <evbarm/dev/plcomreg.h>
#include <evbarm/dev/plcomvar.h>
#endif
#include "opt_evbarm_boardtype.h"
static vaddr_t get_ttb(void);
static void setup_real_page_tables(void);
//static void entropy_init(void);
/*
* Static device map for i.MX23 peripheral address space.
*/
#define _A(a) ((a) & ~L1_S_OFFSET)
#define _S(s) (((s) + L1_S_SIZE - 1) & ~(L1_S_SIZE-1))
static const struct pmap_devmap imx23_devmap[] = {
{
_A(APBH_BASE), /* Virtual address. */
_A(APBH_BASE), /* Physical address. */
_S(APBH_SIZE + APBX_SIZE), /* APBX located after APBH. */
VM_PROT_READ|VM_PROT_WRITE, /* Protection bits. */
PTE_NOCACHE /* Cache attributes. */
},
{ 0, 0, 0, 0, 0 }
};
#undef _A
#undef _S
static vm_offset_t physical_freestart;
static vm_offset_t physical_freeend;
static u_int free_pages;
//static rndsave_t imx23_boot_rsp;
BootConfig bootconfig;
vm_offset_t physical_start;
vm_offset_t physical_end;
char *boot_args;
paddr_t msgbufphys;
extern char KERNEL_BASE_phys;
extern char KERNEL_BASE_virt;
extern char _end[];
extern char __data_start[];
extern char _edata[];
extern char __bss_start[];
extern char __bss_end__[];
extern pv_addr_t kernelstack;
extern u_int data_abort_handler_address;
extern u_int prefetch_abort_handler_address;
/* Define various stack sizes in pages. */
#define FIQ_STACK_SIZE 1
#define IRQ_STACK_SIZE 1
#define ABT_STACK_SIZE 1
#define UND_STACK_SIZE 1
/* Macros to translate between physical and virtual addresses. */
#define KERNEL_BASE_PHYS ((paddr_t)&KERNEL_BASE_phys)
#define KERNEL_BASE_VIRT ((vaddr_t)&KERNEL_BASE_virt)
#define KERN_VTOPHYS(va) \
((paddr_t)((vaddr_t)va - KERNEL_BASE_VIRT + KERNEL_BASE_PHYS))
#define KERN_PHYSTOV(pa) \
((vaddr_t)((paddr_t)pa - KERNEL_BASE_PHYS + KERNEL_BASE_VIRT))
#define KERNEL_PT_SYS 0 /* L2 table for mapping vectors page. */
#define KERNEL_PT_KERNEL 1 /* L2 table for mapping kernel. */
#define KERNEL_PT_KERNEL_NUM 4
#define KERNEL_PT_VMDATA (KERNEL_PT_KERNEL + KERNEL_PT_KERNEL_NUM)
/* Page tables for mapping kernel VM */
#define KERNEL_PT_VMDATA_NUM 4 /* start with 16MB of KVM */
#define NUM_KERNEL_PTS (KERNEL_PT_VMDATA + KERNEL_PT_VMDATA_NUM)
pv_addr_t kernel_pt_table[NUM_KERNEL_PTS];
#define KERNEL_VM_BASE (KERNEL_BASE + 0x01000000)
#define KERNEL_VM_SIZE (0xf0000000 - KERNEL_VM_BASE)
#define REG_RD(reg) *(volatile uint32_t *)(reg)
#define REG_WR(reg, val) \
do { \
*(volatile uint32_t *)((reg)) = val; \
} while (0)
/*
* Initialize everything and return new svc stack pointer.
*/
u_int
initarm(void *arg)
{
if (set_cpufuncs())
panic("set_cpufuncs failed");
pmap_devmap_bootstrap(get_ttb(), imx23_devmap);
cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
consinit();
//entropy_init();
/* Talk to the user. */
#define BDSTR(s) _BDSTR(s)
#define _BDSTR(s) #s
printf("\nNetBSD/evbarm (" BDSTR(EVBARM_BOARDTYPE) ") booting ...\n");
#undef BDSTR
#undef _BDSTR
boot_args[0] = '\0';
#ifdef VERBOSE_INIT_ARM
printf("initarm: Configuring system ...\n");
#endif
physical_start = DRAM_BASE;
physical_end = DRAM_BASE + MEMSIZE * 1024 * 1024;
physmem = (physical_end - physical_start) / PAGE_SIZE;
/* bootconfig is used by cpu_dump() and cousins. */
bootconfig.dramblocks = 1;
bootconfig.dram[0].address = DRAM_BASE;
bootconfig.dram[0].pages = physmem;
/*
* Our kernel is at the beginning of the DRAM, so set our free space to
* all the memory after the kernel.
*/
physical_freestart = KERN_VTOPHYS(round_page((vaddr_t) _end));
physical_freeend = physical_end;
free_pages = (physical_freeend - physical_freestart) / PAGE_SIZE;
#ifdef VERBOSE_INIT_ARM
/* Tell the user about the memory. */
printf("physmemory: %d pages at 0x%08lx -> 0x%08lx\n", physmem,
physical_start, physical_end - 1);
#endif
/*
* Set up first and second level page tables. Pages of memory will be
* allocated and mapped for structures required for system operation.
* kernel_l1pt, kernel_pt_table[], systempage, irqstack, abtstack,
* undstack, kernelstack, msgbufphys will be set to point to the memory
* that was allocated for them.
*/
setup_real_page_tables();
#ifdef VERBOSE_INIT_ARM
printf("freestart = 0x%08lx, free_pages = %d (0x%08x)\n",
physical_freestart, free_pages, free_pages);
#endif
uvm_lwp_setuarea(&lwp0, kernelstack.pv_va);
#ifdef VERBOSE_INIT_ARM
printf("bootstrap done.\n");
#endif
/* Copy vectors from page0 to vectors page. */
arm32_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
#ifdef VERBOSE_INIT_ARM
printf("init subsystems: stacks ");
#endif
set_stackptr(PSR_FIQ32_MODE,
fiqstack.pv_va + FIQ_STACK_SIZE * PAGE_SIZE);
set_stackptr(PSR_IRQ32_MODE,
irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE);
set_stackptr(PSR_ABT32_MODE,
abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE);
set_stackptr(PSR_UND32_MODE,
undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE);
#ifdef VERBOSE_INIT_ARM
printf("vectors ");
#endif
data_abort_handler_address = (u_int)data_abort_handler;
prefetch_abort_handler_address = (u_int)prefetch_abort_handler;
undefined_handler_address = (u_int)undefinedinstruction_bounce;
#ifdef VERBOSE_INIT_ARM
printf("undefined ");
#endif
undefined_init();
/* Load memory into UVM. */
#ifdef VERBOSE_INIT_ARM
printf("page ");
#endif
uvm_setpagesize();
uvm_page_physload(atop(physical_freestart), atop(physical_freeend),
atop(physical_freestart), atop(physical_freeend),
VM_FREELIST_DEFAULT);
/* Boot strap pmap telling it where the kernel page table is. */
#ifdef VERBOSE_INIT_ARM
printf("pmap ");
#endif
pmap_bootstrap(KERNEL_VM_BASE, KERNEL_VM_BASE + KERNEL_VM_SIZE);
#ifdef VERBOSE_INIT_ARM
printf("done.\n");
#endif
#ifdef __HAVE_MEMORY_DISK__
md_root_setconf(memory_disk, sizeof memory_disk);
#endif
#ifdef BOOTHOWTO
boothowto |= BOOTHOWTO;
#endif
#ifdef KGDB
if (boothowto & RB_KDB) {
kgdb_debug_init = 1;
kgdb_connect(1);
}
#endif
#ifdef DDB
db_machine_init();
if (boothowto & RB_KDB)
Debugger();
#endif
return kernelstack.pv_va + USPACE_SVC_STACK_TOP;
}
/*
* Return TTBR (Translation Table Base Register) value from coprocessor.
*/
static vaddr_t
get_ttb(void)
{
vaddr_t ttb;
__asm volatile("mrc p15, 0, %0, c2, c0, 0" : "=r" (ttb));
return ttb;
}
/*
* valloc_pages() is used to allocate free memory to be used for kernel pages.
* Virtual and physical addresses of the allocated memory are saved for the
* later use by the structures:
*
* - kernel_l1pt which holds the address of the kernel's L1 translaton table.
* - kernel_pt_table[] holds the addresses of the kernel's L2 page tables.
*
* pmap_link_l2pt() is used to create link from L1 table entry to the L2 page
* table. Link is a reference to coarse page table which has 256 entries,
* splitting the 1MB that the table describes into 4kB blocks.
*
* pmap_map_entry() updates the PTE in L2 PT for an VA to point to single
* physical page previously allocated.
*
* pmap_map_chunk() maps a chunk of memory using the most efficient
* mapping possible (section, large page, small page) into the provided L1 and
* L2 tables at the specified virtual address. pmap_map_chunk() excepts linking
* to be done before it is called for chunks smaller than a section.
*/
static void
setup_real_page_tables(void)
{
/*
* Define a macro to simplify memory allocation. As we allocate the
* memory, make sure that we don't walk over our temporary first level
* translation table.
*/
#define valloc_pages(var, np) \
(var).pv_pa = physical_freestart; \
physical_freestart += ((np) * PAGE_SIZE); \
if (physical_freestart > (physical_freeend - L1_TABLE_SIZE)) \
panic("%s: out of memory", __func__); \
free_pages -= (np); \
(var).pv_va = KERN_PHYSTOV((var).pv_pa); \
memset((char *)(var).pv_va, 0, ((np) * PAGE_SIZE));
int loop, pt_index;
pt_index = 0;
kernel_l1pt.pv_pa = 0;
kernel_l1pt.pv_va = 0;
for (loop = 0; loop <= NUM_KERNEL_PTS; ++loop) {
/* Are we 16kB aligned for an L1? */
if ((physical_freestart & (L1_TABLE_SIZE - 1)) == 0 &&
kernel_l1pt.pv_pa == 0) {
valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
} else {
valloc_pages(kernel_pt_table[pt_index],
L2_TABLE_SIZE / PAGE_SIZE);
++pt_index;
}
}
/* Make sure L1 page table is aligned to 16kB. */
if (!kernel_l1pt.pv_pa ||
(kernel_l1pt.pv_pa & (L1_TABLE_SIZE - 1)) != 0)
panic("%s: Failed to align the kernel page directory",
__func__);
/*
* Allocate a page for the system page mapped to ARM_VECTORS_HIGH.
* This page will just contain the system vectors and can be shared by
* all processes.
*/
valloc_pages(systempage, 1);
systempage.pv_va = ARM_VECTORS_HIGH;
/* Allocate stacks for all modes. */
valloc_pages(fiqstack, FIQ_STACK_SIZE);
valloc_pages(irqstack, IRQ_STACK_SIZE);
valloc_pages(abtstack, ABT_STACK_SIZE);
valloc_pages(undstack, UND_STACK_SIZE);
valloc_pages(kernelstack, UPAGES);
/* Allocate the message buffer. */
pv_addr_t msgbuf;
int msgbuf_pgs = round_page(MSGBUFSIZE) / PAGE_SIZE;
valloc_pages(msgbuf, msgbuf_pgs);
msgbufphys = msgbuf.pv_pa;
vaddr_t l1_va = kernel_l1pt.pv_va;
vaddr_t l1_pa = kernel_l1pt.pv_pa;
/* Map the L2 pages tables in the L1 page table. */
pmap_link_l2pt(l1_va, ARM_VECTORS_HIGH & ~(0x00400000 - 1),
&kernel_pt_table[KERNEL_PT_SYS]);
for (loop = 0; loop < KERNEL_PT_KERNEL_NUM; loop++)
pmap_link_l2pt(l1_va, KERNEL_BASE + loop * 0x00400000,
&kernel_pt_table[KERNEL_PT_KERNEL + loop]);
for (loop = 0; loop < KERNEL_PT_VMDATA_NUM; loop++)
pmap_link_l2pt(l1_va, KERNEL_VM_BASE + loop * 0x00400000,
&kernel_pt_table[KERNEL_PT_VMDATA + loop]);
/* Update the top of the kernel VM. */
pmap_curmaxkvaddr =
KERNEL_VM_BASE + (KERNEL_PT_VMDATA_NUM * 0x00400000);
extern char etext[];
size_t textsize = (uintptr_t)etext - KERNEL_BASE;
size_t totalsize = (uintptr_t)_end - KERNEL_BASE;
u_int logical;
textsize = (textsize + PGOFSET) & ~PGOFSET;
totalsize = (totalsize + PGOFSET) & ~PGOFSET;
logical = 0x00000000; /* offset of kernel in RAM */
logical += pmap_map_chunk(l1_va, KERNEL_BASE + logical,
physical_start + logical, textsize,
VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
logical += pmap_map_chunk(l1_va, KERNEL_BASE + logical,
physical_start + logical, totalsize - textsize,
VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
/* Map the stack pages. */
pmap_map_chunk(l1_va, fiqstack.pv_va, fiqstack.pv_pa,
FIQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
pmap_map_chunk(l1_va, irqstack.pv_va, irqstack.pv_pa,
IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
pmap_map_chunk(l1_va, abtstack.pv_va, abtstack.pv_pa,
ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
pmap_map_chunk(l1_va, undstack.pv_va, undstack.pv_pa,
UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
pmap_map_chunk(l1_va, kernelstack.pv_va, kernelstack.pv_pa,
UPAGES * PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE, PTE_CACHE);
pmap_map_chunk(l1_va, kernel_l1pt.pv_va, kernel_l1pt.pv_pa,
L1_TABLE_SIZE, VM_PROT_READ | VM_PROT_WRITE, PTE_PAGETABLE);
for (loop = 0; loop < NUM_KERNEL_PTS; ++loop)
pmap_map_chunk(l1_va, kernel_pt_table[loop].pv_va,
kernel_pt_table[loop].pv_pa, L2_TABLE_SIZE,
VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
/* Map the vector page. */
pmap_map_entry(l1_va, ARM_VECTORS_HIGH, systempage.pv_pa,
VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
pmap_devmap_bootstrap(l1_va, imx23_devmap);
#ifdef VERBOSE_INIT_ARM
/* Tell the user about where all the bits and pieces live. */
printf("%22s Physical Virtual Num\n", " ");
printf("%22s Starting Ending Starting Ending Pages\n", " ");
static const char mem_fmt[] =
"%20s: 0x%08lx 0x%08lx 0x%08lx 0x%08lx %d\n";
static const char mem_fmt_nov[] =
"%20s: 0x%08lx 0x%08lx %d\n";
printf(mem_fmt, "SDRAM", physical_start, physical_end-1,
KERN_PHYSTOV(physical_start), KERN_PHYSTOV(physical_end-1),
physmem);
printf(mem_fmt, "text section",
KERN_VTOPHYS(KERNEL_BASE), KERN_VTOPHYS(etext-1),
(vaddr_t)KERNEL_BASE, (vaddr_t)etext-1,
(int)(textsize / PAGE_SIZE));
printf(mem_fmt, "data section",
KERN_VTOPHYS(__data_start), KERN_VTOPHYS(_edata),
(vaddr_t)__data_start, (vaddr_t)_edata,
(int)((round_page((vaddr_t)_edata)
- trunc_page((vaddr_t)__data_start)) / PAGE_SIZE));
printf(mem_fmt, "bss section",
KERN_VTOPHYS(__bss_start), KERN_VTOPHYS(__bss_end__),
(vaddr_t)__bss_start, (vaddr_t)__bss_end__,
(int)((round_page((vaddr_t)__bss_end__)
- trunc_page((vaddr_t)__bss_start)) / PAGE_SIZE));
printf(mem_fmt, "L1 page directory",
kernel_l1pt.pv_pa, kernel_l1pt.pv_pa + L1_TABLE_SIZE - 1,
kernel_l1pt.pv_va, kernel_l1pt.pv_va + L1_TABLE_SIZE - 1,
L1_TABLE_SIZE / PAGE_SIZE);
printf(mem_fmt, "Exception Vectors",
systempage.pv_pa, systempage.pv_pa + PAGE_SIZE - 1,
(vaddr_t)ARM_VECTORS_HIGH,
(vaddr_t)ARM_VECTORS_HIGH + PAGE_SIZE - 1, 1);
printf(mem_fmt, "FIQ stack",
fiqstack.pv_pa, fiqstack.pv_pa + (FIQ_STACK_SIZE * PAGE_SIZE) - 1,
fiqstack.pv_va, fiqstack.pv_va + (FIQ_STACK_SIZE * PAGE_SIZE) - 1,
FIQ_STACK_SIZE);
printf(mem_fmt, "IRQ stack",
irqstack.pv_pa, irqstack.pv_pa + (IRQ_STACK_SIZE * PAGE_SIZE) - 1,
irqstack.pv_va, irqstack.pv_va + (IRQ_STACK_SIZE * PAGE_SIZE) - 1,
IRQ_STACK_SIZE);
printf(mem_fmt, "ABT stack",
abtstack.pv_pa, abtstack.pv_pa + (ABT_STACK_SIZE * PAGE_SIZE) - 1,
abtstack.pv_va, abtstack.pv_va + (ABT_STACK_SIZE * PAGE_SIZE) - 1,
ABT_STACK_SIZE);
printf(mem_fmt, "UND stack",
undstack.pv_pa, undstack.pv_pa + (UND_STACK_SIZE * PAGE_SIZE) - 1,
undstack.pv_va, undstack.pv_va + (UND_STACK_SIZE * PAGE_SIZE) - 1,
UND_STACK_SIZE);
printf(mem_fmt, "SVC stack",
kernelstack.pv_pa, kernelstack.pv_pa + (UPAGES * PAGE_SIZE) - 1,
kernelstack.pv_va, kernelstack.pv_va + (UPAGES * PAGE_SIZE) - 1,
UPAGES);
printf(mem_fmt_nov, "Message Buffer",
msgbufphys, msgbufphys + msgbuf_pgs * PAGE_SIZE - 1, msgbuf_pgs);
printf(mem_fmt, "Free Memory", physical_freestart, physical_freeend-1,
KERN_PHYSTOV(physical_freestart), KERN_PHYSTOV(physical_freeend-1),
free_pages);
#endif
cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
cpu_setttb(l1_pa, FALSE);
cpu_tlb_flushID();
cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
return;
}
/*
* Generate initial random bits for rnd_init().
*/
#ifdef notyet
static void
entropy_init(void)
{
uint32_t tmp;
int loop, index;
/* Test if HW_DIGCTL_ENTROPY is feeding random numbers. */
tmp = REG_RD(HW_DIGCTL_BASE + HW_DIGCTL_ENTROPY);
if (tmp == REG_RD(HW_DIGCTL_BASE + HW_DIGCTL_ENTROPY))
return;
index = 0;
for (loop = 0; loop < RND_SAVEWORDS; loop++) {
imx23_boot_rsp.data[index++] = (uint8_t)(tmp);
imx23_boot_rsp.data[index++] = (uint8_t)(tmp>>8);
imx23_boot_rsp.data[index++] = (uint8_t)(tmp>>16);
imx23_boot_rsp.data[index++] = (uint8_t)(tmp>>24);
imx23_boot_rsp.entropy += 32;
tmp = REG_RD(HW_DIGCTL_BASE + HW_DIGCTL_ENTROPY);
}
extern rndsave_t *boot_rsp;
boot_rsp = &imx23_boot_rsp;
return;
}
#endif
/*
* Initialize console.
*/
static struct plcom_instance imx23_pi = {
.pi_type = PLCOM_TYPE_PL011,
.pi_iot = &imx23_bus_space,
.pi_size = PL011COM_UART_SIZE,
.pi_iobase = HW_UARTDBG_BASE
};
#define PLCONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
#define PLCONSPEED 115200
void
consinit(void)
{
/* consinit() is called from also from the main(). */
static int consinit_called = 0;
if (consinit_called)
return;
plcomcnattach(&imx23_pi, PLCONSPEED, IMX23_UART_CLK, PLCONMODE, 0);
consinit_called = 1;
return;
}
/*
* Reboot or halt the system.
*/
void
cpu_reboot(int howto, char *bootstr)
{
static int cpu_reboot_called = 0;
boothowto |= howto;
/*
* If this is the first invocation of cpu_reboot() and the RB_NOSYNC
* flag is not set in howto; sync and unmount the system disks by
* calling vfs_shutdown(9) and set the time of day clock by calling
* resettodr(9).
*/
if (!cpu_reboot_called && !(boothowto & RB_NOSYNC)) {
vfs_shutdown();
resettodr();
}
cpu_reboot_called = 1;
IRQdisable; /* FIQ's stays on because they are special. */
/*
* If rebooting after a crash (i.e., if RB_DUMP is set in howto, but
* RB_HALT is not), save a system crash dump.
*/
if ((boothowto & RB_DUMP) && !(boothowto & RB_HALT))
panic("please implement crash dump!"); // XXX
/* Run any shutdown hooks by calling pmf_system_shutdown(9). */
pmf_system_shutdown(boothowto);
printf("system %s.\n", boothowto & RB_HALT ? "halted" : "rebooted");
if (boothowto & RB_HALT) {
/* Enable i.MX233 wait-for-interrupt mode. */
REG_WR(HW_CLKCTRL_BASE + HW_CLKCTRL_CPU,
(REG_RD(HW_CLKCTRL_BASE + HW_CLKCTRL_CPU) |
HW_CLKCTRL_CPU_INTERRUPT_WAIT));
/* Disable FIQ's and wait for interrupt (which never arrives) */
__asm volatile( \
"mrs r0, cpsr\n\t" \
"orr r0, #0x40\n\t" \
"msr cpsr_c, r0\n\t" \
"mov r0, #0\n\t" \
"mcr p15, 0, r0, c7, c0, 4\n\t"
);
for(;;);
/* NOT REACHED */
}
/* Reboot the system. */
REG_WR(HW_RTC_BASE + HW_RTC_WATCHDOG, 10000);
REG_WR(HW_RTC_BASE + HW_RTC_CTRL_SET, HW_RTC_CTRL_WATCHDOGEN);
REG_WR(HW_RTC_BASE + HW_RTC_WATCHDOG, 0);
for(;;);
/* NOT REACHED */
}
/*
* Delay us microseconds.
*/
void
delay(unsigned int us)
{
uint32_t start;
uint32_t now;
uint32_t elapsed;
uint32_t total;
uint32_t last;
total = 0;
last = 0;
start = REG_RD(HW_DIGCTL_BASE + HW_DIGCTL_MICROSECONDS);
do {
now = REG_RD(HW_DIGCTL_BASE + HW_DIGCTL_MICROSECONDS);
if (start <= now)
elapsed = now - start;
else /* Take care of overflow. */
elapsed = (UINT32_MAX - start) + 1 + now;
total += elapsed - last;
last = elapsed;
} while (total < us);
return;
}

View File

@ -0,0 +1,185 @@
/* $Id: imx23_olinuxino_start.S,v 1.1 2012/11/20 19:08:46 jkunz Exp $ */
/*
* Copyright (c) 2012 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Petri Laakso.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <machine/asm.h>
#include <machine/pmap.h>
#include <arm/armreg.h>
#include <arm/imx/imx23var.h>
#include <arm/imx/imx23_uartdbgreg.h>
.section .start,"ax",%progbits
.global _C_LABEL(olinuxino_start)
_C_LABEL(olinuxino_start):
/*
* Set up the first level page table. The page table has 4096 section
* page table entries which each one maps 1MB of virtual memory.
* Section entries are mapped from mmu_init_table to the page table.
*/
l1pt_p .req r0
mit_p .req r1
va .req r2
pa .req r3
n_sec .req r4
attr .req r5
pte_p .req r6
sec .req r7
tmp .req r8
tmp2 .req r9
ldr l1pt_p, Ll1_pt
/* Zero the page table. */
mov tmp, #0
add tmp2, l1pt_p, #L1_TABLE_SIZE
1: str tmp, [l1pt_p], #4
cmp l1pt_p, tmp2
blt 1b
ldr l1pt_p, Ll1_pt
/* Map sections. */
ldr mit_p, =mmu_init_table
ldmia mit_p!, {va, pa, n_sec, attr}
/*
* Calculate PTE addresses for a MVA's.
*
* Bits[31:14] of the Translation Table Base register are concatenated
* with bits[31:20] of the modified virtual address and two zero bits
* to produce a physical address of the page table entry for a MVA:
*
* PTE = (TTBR & 0xffffc000) | ((MVA & 0xfff00000)>>18)
*/
3: ldr tmp, =0xffffc000
and pte_p, l1pt_p, tmp
ldr tmp, =0xfff00000
and va, va, tmp
mov va, va, LSR #18
orr pte_p, pte_p, va
2: orr sec, pa, attr
str sec, [pte_p], #4 /* Store #n_sec sections to the page */
add pa, pa, #0x100000 /* table. */
subs n_sec, #1
bne 2b
ldmia mit_p!, {va, pa, n_sec, attr}
cmp n_sec, #0
bne 3b
/*
* The Translation Table Base Register holds the physical address of
* the page table.
*/
mcr p15, 0, l1pt_p, c2, c0, 0
.unreq l1pt_p
.unreq mit_p
.unreq va
.unreq pa
.unreq n_sec
.unreq attr
.unreq pte_p
.unreq sec
.unreq tmp
.unreq tmp2
/*
* Sections are in domain 0 and we set D0 access control to client
* mode, which means AP bits are checked. Since we are running
* privileged mode and APs are kernel read/write, access is granted.
*/
mov r0, #DOMAIN_CLIENT<<(PMAP_DOMAIN_KERNEL*2)
mcr p15, 0, r0, c3, c0, 0
/*
* Enable the MMU.
*/
mov r0, #0
mcr p15, 0, r0, c8, c7, 0 /* Invalidate TLB. */
mrc p15, 0, r0, c1, c0, 0
ldr r1, =(CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE \
| CPU_CONTROL_AFLT_ENABLE | CPU_CONTROL_MMU_ENABLE)
orr r0, r0, r1
mcr p15, 0, r0, c1, c0, 0
nop /* Fetch flat. */
nop /* Fetch flat. */
/*
* Jump to start in locore.S. start sets the sp point to DRAM, zeroes
* the .bss and calls initarm. start never returns.
*/
ldr pc, =start
/* NOTREACHED */
/*
* Initial first level translation table on a 16kB boundary located at the
* end of the DRAM.
*
* The translation table has 4096 32-bit section entries, each describing 1MB of
* virtual memory which means 4GB of virtual memory to be addressed.
*/
Ll1_pt:
.word (DRAM_BASE + MEMSIZE * 1024 * 1024 - L1_TABLE_SIZE)
#define MMU_INIT(va,pa,n_sec,attr) \
.word va; \
.word pa; \
.word n_sec; \
.word attr;
mmu_init_table:
/* On-chip RAM */
MMU_INIT(0x00000000, 0x00000000,
1,
L1_S_AP(AP_KRW) | L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_S_PROTO)
/* On-chip ROM (Vectors) */
MMU_INIT(0xFFFF0000, 0xFFFF0000,
1,
L1_S_AP(AP_KRW) | L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_S_PROTO)
/* DRAM */
MMU_INIT(KERNEL_BASE_virt, KERNEL_BASE_phys,
MEMSIZE,
L1_S_AP(AP_KRW) | L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_S_C |\
L1_S_B | L1_S_PROTO)
/* Peripherals */
MMU_INIT(APBH_BASE, APBH_BASE,
1,
L1_S_AP(AP_KRW) | L1_S_DOM(PMAP_DOMAIN_KERNEL) | L1_S_PROTO)
MMU_INIT(0, 0, 0, 0)

View File

@ -1,6 +1,7 @@
# $NetBSD: Makefile,v 1.2 2012/01/30 03:28:34 nisimura Exp $
# $NetBSD: Makefile,v 1.3 2012/11/20 19:17:03 jkunz Exp $
SUBDIR+= gzboot
SUBDIR+= boot2440
SUBDIR+= bootimx23
.include <bsd.subdir.mk>

View File

@ -0,0 +1,52 @@
# $Id: Makefile,v 1.1 2012/11/20 19:08:46 jkunz Exp $
S= ${.CURDIR}/../../../../
PROG= bootimx23
SRCS= boot_prep.c power_prep.c clock_prep.c emi_prep.c \
pinctrl_prep.c common.c
.include <bsd.own.mk>
CLEANFILES+= ${PROG}
CFLAGS+= -Wall -Wno-main -ffreestanding -march=armv5te -mtune=arm926ej-s
CPPFLAGS+= -D_STANDALONE
CPPFLAGS+= -nostdinc -I. -I${.CURDIR} -I${.OBJDIR} -I${S} -I${S}/arch
#CPPFLAGS+= -DDEBUG
#DBG= -g
LIBCRT0= # nothing
LIBCRTBEGIN= # nothing
LIBCRTEND= # nothing
LIBC= # nothing
MAN= # no manual page
NOMAN= # defined
STRIPFLAG=
BINMODE= 444
RELOC= 0x00000000
ENTRY= _start
### find out what to use for libkern
KERN_AS= library
.include "${S}/lib/libkern/Makefile.inc"
LIBKERN= ${KERNLIB}
### find out what to use for libsa
SA_AS= library
.include "${S}/lib/libsa/Makefile.inc"
LIBSA= ${SALIB}
${PROG}: ${OBJS} ${LIBSA} ${LIBKERN}
${LD} -N -Ttext ${RELOC} -Bstatic -e ${ENTRY} -o ${.TARGET} \
${OBJS} ${LIBSA} ${LIBKERN}
cleandir distclean: .WAIT cleanlibdir
cleanlibdir:
-rm -rf lib
.include <bsd.klinks.mk>
.include <bsd.prog.mk>

View File

@ -0,0 +1,68 @@
/* $Id: boot_prep.c,v 1.1 2012/11/20 19:08:46 jkunz Exp $ */
/*
* Copyright (c) 2012 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Petri Laakso.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/cdefs.h>
#include <arm/imx/imx23_digctlreg.h>
#include <lib/libsa/stand.h>
#include "common.h"
/*
* Initialize i.MX23 power, clock and DRAM.
*/
int
_start(void)
{
/* Make sure timer is running */
REG_WRITE(HW_DIGCTL_BASE + HW_DIGCTL_CTRL_CLR,
HW_DIGCTL_CTRL_XTAL24M_GATE);
printf("\n\rBooting");
power_prep();
putchar('.');
clock_prep();
putchar('.');
pinctrl_prep();
delay_us(1000);
putchar('.');
emi_prep();
printf("done.\n\r");
return 0;
}

View File

@ -0,0 +1,31 @@
/* $Id: bootimx23.bd,v 1.1 2012/11/20 19:08:46 jkunz Exp $ */
/*
* elftosb command file.
*
* Generate boot image by issuing:
* $ elftosb -V -c bootimx23.bd -z -o bootimx23.sb
*
* Verify generated boot image:
* $ sbtool -x 2 bootimx23.sb
*
*/
options {
toolset = "GNU";
}
sources {
boot_prep="./boot_prep.elf";
netbsd="./netbsd";
}
section (0) {
// Initialize power, clocks and DRAM.
load boot_prep;
call boot_prep;
// Load and start NetBSD kernel.
load netbsd;
jump netbsd;
}

View File

@ -0,0 +1,255 @@
/* $Id: clock_prep.c,v 1.1 2012/11/20 19:08:46 jkunz Exp $ */
/*
* Copyright (c) 2012 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Petri Laakso.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#include <arm/imx/imx23_clkctrlreg.h>
#include <lib/libsa/stand.h>
#include "common.h"
void enable_pll(void);
void enable_ref_cpu(int);
void enable_ref_emi(int);
void enable_ref_io(int);
void use_ref_cpu(void);
void use_ref_emi(void);
void use_ref_io(void);
void set_hbus_div(int);
void set_emi_div(int);
void set_ssp_div(int);
/* Clock frequences after clock_prep() */
#define CPU_FRAC 0x13 /* CPUCLK @ 454.74 MHz */
#define HBUS_DIV 0x3 /* AHBCLK @ 151.58 MHz */
#define EMI_FRAC 0x21 /* EMICLK @ 130.91 MHz */
#define EMI_DIV 0x2
#define IO_FRAC 0x12 /* IOCLK @ 480.00 MHz */
#define SSP_DIV 0x5 /* SSPCLK @ 96.00 MHz */
/* Offset to frac register for byte store instructions. (strb) */
#define HW_CLKCTRL_FRAC_CPU (HW_CLKCTRL_FRAC+0)
#define HW_CLKCTRL_FRAC_EMI (HW_CLKCTRL_FRAC+1)
#define HW_CLKCTRL_FRAC_IO (HW_CLKCTRL_FRAC+3)
#define CLKCTRL_RD(reg) *(volatile uint32_t *)((HW_CLKCTRL_BASE) + (reg))
#define CLKCTRL_WR(reg, val) \
do { \
*(volatile uint32_t *)((HW_CLKCTRL_BASE) + (reg)) = val; \
} while (0)
#define CLKCTRL_WR_BYTE(reg, val) \
do { \
*(volatile uint8_t *)((HW_CLKCTRL_BASE) + (reg)) = val; \
} while (0)
/*
* Initializes fast PLL based clocks for CPU, HBUS and DRAM.
*/
int
clock_prep(void)
{
enable_pll();
enable_ref_cpu(CPU_FRAC);
enable_ref_emi(EMI_FRAC);
enable_ref_io(IO_FRAC);
set_emi_div(EMI_DIV);
set_hbus_div(HBUS_DIV);
delay_us(1000);
use_ref_cpu();
//delay_us(1000);
use_ref_emi();
use_ref_io();
set_ssp_div(SSP_DIV);
return 0;
}
/*
* Turn PLL on and wait until it's locked to 480 MHz.
*/
void
enable_pll(void)
{
CLKCTRL_WR(HW_CLKCTRL_PLLCTRL0_SET, HW_CLKCTRL_PLLCTRL0_POWER);
while (!(CLKCTRL_RD(HW_CLKCTRL_PLLCTRL1) & HW_CLKCTRL_PLLCTRL1_LOCK));
return;
}
/*
* Enable fractional divider clock ref_cpu with divide value "frac".
*/
void
enable_ref_cpu(int frac)
{
uint32_t reg;
reg = CLKCTRL_RD(HW_CLKCTRL_FRAC);
reg &= ~(HW_CLKCTRL_FRAC_CLKGATECPU | HW_CLKCTRL_FRAC_CPUFRAC);
reg |= __SHIFTIN(frac, HW_CLKCTRL_FRAC_CPUFRAC);
CLKCTRL_WR_BYTE(HW_CLKCTRL_FRAC_CPU, reg);
return;
}
/*
* Enable fractional divider clock ref_emi with divide value "frac".
*/
void
enable_ref_emi(int frac)
{
uint32_t reg;
reg = CLKCTRL_RD(HW_CLKCTRL_FRAC);
reg &= ~(HW_CLKCTRL_FRAC_CLKGATEEMI | HW_CLKCTRL_FRAC_EMIFRAC);
reg |= __SHIFTIN(frac, HW_CLKCTRL_FRAC_EMIFRAC);
CLKCTRL_WR_BYTE(HW_CLKCTRL_FRAC_EMI, (reg >> 8));
return;
}
/*
* Enable fractional divider clock ref_io with divide value "frac".
*/
void
enable_ref_io(int frac)
{
uint32_t reg;
reg = CLKCTRL_RD(HW_CLKCTRL_FRAC);
reg &= ~(HW_CLKCTRL_FRAC_CLKGATEIO | HW_CLKCTRL_FRAC_IOFRAC);
reg |= __SHIFTIN(frac, HW_CLKCTRL_FRAC_IOFRAC);
CLKCTRL_WR_BYTE(HW_CLKCTRL_FRAC_IO, (reg >> 24));
return;
}
/*
* Divide CLK_P by "div" to get CLK_H frequency.
*/
void
set_hbus_div(int div)
{
uint32_t reg;
reg = CLKCTRL_RD(HW_CLKCTRL_HBUS);
reg &= ~(HW_CLKCTRL_HBUS_DIV);
reg |= __SHIFTIN(div, HW_CLKCTRL_HBUS_DIV);
while (CLKCTRL_RD(HW_CLKCTRL_HBUS) & HW_CLKCTRL_HBUS_BUSY);
CLKCTRL_WR(HW_CLKCTRL_HBUS, reg);
return;
}
/*
* ref_emi is divied "div" to get CLK_EMI.
*/
void
set_emi_div(int div)
{
uint32_t reg;
reg = CLKCTRL_RD(HW_CLKCTRL_EMI);
reg &= ~(HW_CLKCTRL_EMI_DIV_EMI);
reg |= __SHIFTIN(div, HW_CLKCTRL_EMI_DIV_EMI);
CLKCTRL_WR(HW_CLKCTRL_EMI, reg);
return;
}
/*
* ref_io is divied "div" to get CLK_SSP.
*/
void
set_ssp_div(int div)
{
uint32_t reg;
reg = CLKCTRL_RD(HW_CLKCTRL_SSP);
reg &= ~(HW_CLKCTRL_SSP_DIV);
reg |= __SHIFTIN(div, HW_CLKCTRL_SSP_DIV);
CLKCTRL_WR(HW_CLKCTRL_SSP, reg);
return;
}
/*
* Transition from ref_xtal to use ref_cpu.
*/
void
use_ref_cpu(void)
{
CLKCTRL_WR(HW_CLKCTRL_CLKSEQ_CLR, HW_CLKCTRL_CLKSEQ_BYPASS_CPU);
return;
}
/*
* Transition from ref_xtal to use ref_emi and source CLK_EMI from ref_emi.
*/
void
use_ref_emi(void)
{
uint32_t reg;
/* Enable ref_emi. */
CLKCTRL_WR(HW_CLKCTRL_CLKSEQ_CLR, HW_CLKCTRL_CLKSEQ_BYPASS_EMI);
/* CLK_EMI sourced by the ref_emi. */
reg = CLKCTRL_RD(HW_CLKCTRL_EMI);
reg &= ~(HW_CLKCTRL_EMI_CLKGATE);
CLKCTRL_WR(HW_CLKCTRL_EMI, reg);
return;
}
/*
* Transition from ref_xtal to use ref_io and source CLK_SSP from ref_io.
*/
void
use_ref_io(void)
{
uint32_t reg;
/* Enable ref_io for SSP. */
CLKCTRL_WR(HW_CLKCTRL_CLKSEQ_CLR, HW_CLKCTRL_CLKSEQ_BYPASS_SSP);
/* CLK_SSP sourced by the ref_io. */
reg = CLKCTRL_RD(HW_CLKCTRL_SSP);
reg &= ~(HW_CLKCTRL_SSP_CLKGATE);
CLKCTRL_WR(HW_CLKCTRL_SSP, reg);
return;
}

View File

@ -0,0 +1,69 @@
/* $Id: common.c,v 1.1 2012/11/20 19:08:46 jkunz Exp $ */
/*
* Copyright (c) 2012 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Petri Laakso.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/cdefs.h>
#include <arm/imx/imx23_digctlreg.h>
#include <arm/imx/imx23_uartdbgreg.h>
#include "common.h"
/*
* Delay "delay" microseconds.
*/
void
delay_us(unsigned int delay)
{
/* Set microsecond timer to 0 */
REG_WRITE(HW_DIGCTL_BASE + HW_DIGCTL_MICROSECONDS_CLR, 0xFFFFFFFF);
while (REG_READ(HW_DIGCTL_BASE + HW_DIGCTL_MICROSECONDS) < delay);
return;
}
/*
* Write character to debug UART.
*/
void
putchar(int ch)
{
/* Wait until transmit FIFO has space for the new character. */
while (REG_READ(HW_UARTDBG_BASE + HW_UARTDBGFR) & HW_UARTDBGFR_TXFF);
REG_WRITE_BYTE(HW_UARTDBG_BASE + HW_UARTDBGDR,
__SHIFTIN(ch, HW_UARTDBGDR_DATA));
return;
}

View File

@ -0,0 +1,52 @@
/* $Id: common.h,v 1.1 2012/11/20 19:08:46 jkunz Exp $ */
/*
* Copyright (c) 2012 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Petri Laakso.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _BOOTIMX23_COMMON_
#define _BOOTIMX23_COMMON_
#define REG_READ(reg) *(volatile uint32_t *)(reg)
#define REG_WRITE(reg, val) \
do { \
*(volatile uint32_t *)((reg)) = val; \
} while (0)
#define REG_WRITE_BYTE(reg, val) \
do { \
*(volatile uint8_t *)((reg)) = val; \
} while (0)
int clock_prep(void);
int emi_prep(void);
int pinctrl_prep(void);
int power_prep(void);
void delay_us(unsigned int);
void putchar(int);
#endif /* !_BOOTIMX23_COMMON_ */

View File

@ -0,0 +1,151 @@
/* $Id: emi_prep.c,v 1.1 2012/11/20 19:08:46 jkunz Exp $ */
/*
* Copyright (c) 2012 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Petri Laakso.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#include <arm/imx/imx23_emireg.h>
#include <lib/libsa/stand.h>
#include "common.h"
void init_dram_registers(void);
void start_dram(void);
uint32_t get_dram_int_status(void);
/*
* Initialize external DRAM memory.
*/
int
emi_prep(void)
{
init_dram_registers();
start_dram();
return 0;
}
/*
* DRAM register values for 32Mx16 hy5du121622dtp-d43 DDR module.
*
* Register values were copied from Freescale's imx-bootlets-src-10.05.02
* source code, init_ddr_mt46v32m16_133Mhz() function. Only change to those
* settings were to HW_DRAM_CTL19_DQS_OUT_SHIFT which was set to 16 as a result
* from trial and error.
*/
void
init_dram_registers(void)
{
uint32_t reg;
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL00, 0x01010001);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL01, 0x00010100);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL02, 0x01000101);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL03, 0x00000001);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL04, 0x00000101);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL05, 0x00000000);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL06, 0x00010000);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL07, 0x01000001);
// HW_DRAM_CTL08 initialized last.
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL09, 0x00000001);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL10, 0x07000200);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL11, 0x00070202);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL12, 0x02020000);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL13, 0x04040a01);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL14, 0x00000201);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL15, 0x02040000);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL16, 0x02000000);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL17, 0x19000f08);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL18, 0x0d0d0000);
// REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL19, 0x02021313);
reg = __SHIFTIN(2, HW_DRAM_CTL19_DQS_OUT_SHIFT_BYPASS) |
__SHIFTIN(16, HW_DRAM_CTL19_DQS_OUT_SHIFT) |
__SHIFTIN(19, HW_DRAM_CTL19_DLL_DQS_DELAY_BYPASS_1) |
__SHIFTIN(19, HW_DRAM_CTL19_DLL_DQS_DELAY_BYPASS_0);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL19, reg);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL20, 0x02061521);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL21, 0x0000000a);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL22, 0x00080008);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL23, 0x00200020);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL24, 0x00200020);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL25, 0x00200020);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL26, 0x000003f7);
// HW_DRAM_CTL27
// HW_DRAM_CTL28
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL29, 0x00000020);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL30, 0x00000020);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL31, 0x00c80000);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL32, 0x000a23cd);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL33, 0x000000c8);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL34, 0x00006665);
// HW_DRAM_CTL35 is read only register
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL36, 0x00000101);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL37, 0x00040001);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL38, 0x00000000);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL39, 0x00000000);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL40, 0x00010000);
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL08, 0x01000000);
return;
}
/*
* Start DRAM module. After return DRAM is ready to use.
*/
void
start_dram(void)
{
uint32_t reg;
reg = REG_READ(HW_DRAM_BASE + HW_DRAM_CTL08);
reg |= HW_DRAM_CTL08_START;
REG_WRITE(HW_DRAM_BASE + HW_DRAM_CTL08, reg);
/* Wait until DRAM initialization is complete. */
while(!(get_dram_int_status() & (1<<2)));
return;
}
/*
* Return DRAM controller interrupt status register.
*/
uint32_t
get_dram_int_status(void)
{
uint32_t reg;
reg = REG_READ(HW_DRAM_BASE + HW_DRAM_CTL18);
return __SHIFTOUT(reg, HW_DRAM_CTL18_INT_STATUS);
}

View File

@ -0,0 +1,485 @@
/* $Id: pinctrl_prep.c,v 1.1 2012/11/20 19:08:46 jkunz Exp $ */
/*
* Copyright (c) 2012 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Petri Laakso.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#include <arm/imx/imx23_pinctrlreg.h>
#include <lib/libsa/stand.h>
#include "common.h"
void configure_emi_mux(void);
void configure_emi_drive(int);
void disable_emi_padkeepers(void);
void configure_ssp_mux();
void configure_ssp_drive(int);
void configure_ssp_pullups(void);
/* EMI pins output drive strengths */
#define DRIVE_04_MA 0x0 /* 4 mA */
#define DRIVE_08_MA 0x1 /* 8 mA */
#define DRIVE_12_MA 0x2 /* 12 mA */
#define DRIVE_16_MA 0x3 /* 16 mA */
/*
* Configure external EMI pins.
*/
int
pinctrl_prep(void)
{
REG_WRITE(HW_PINCTRL_BASE + HW_PINCTRL_CTRL_CLR,
(HW_PINCTRL_CTRL_SFTRST | HW_PINCTRL_CTRL_CLKGATE));
/* EMI. */
configure_emi_mux();
configure_emi_drive(DRIVE_12_MA);
disable_emi_padkeepers();
/* SSP. */
configure_ssp_mux();
configure_ssp_drive(DRIVE_16_MA);
configure_ssp_pullups();
return 0;
}
/*
* Configure external EMI pins to be used for DRAM.
*/
void
configure_emi_mux(void)
{
REG_WRITE(HW_PINCTRL_BASE + HW_PINCTRL_MUXSEL4_CLR, (
HW_PINCTRL_MUXSEL4_BANK2_PIN15 | /* Pin 108, EMI_A06 */
HW_PINCTRL_MUXSEL4_BANK2_PIN14 | /* Pin 107, EMI_A05 */
HW_PINCTRL_MUXSEL4_BANK2_PIN13 | /* Pin 109, EMI_A04 */
HW_PINCTRL_MUXSEL4_BANK2_PIN12 | /* Pin 110, EMI_A03 */
HW_PINCTRL_MUXSEL4_BANK2_PIN11 | /* Pin 111, EMI_A02 */
HW_PINCTRL_MUXSEL4_BANK2_PIN10 | /* Pin 112, EMI_A01 */
HW_PINCTRL_MUXSEL4_BANK2_PIN09) /* Pin 113, EMI_A00 */
);
REG_WRITE(HW_PINCTRL_BASE + HW_PINCTRL_MUXSEL5_CLR, (
HW_PINCTRL_MUXSEL5_BANK2_PIN31 | /* Pin 114, EMI_WEN */
HW_PINCTRL_MUXSEL5_BANK2_PIN30 | /* Pin 98, EMI_RASN */
HW_PINCTRL_MUXSEL5_BANK2_PIN29 | /* Pin 115, EMI_CKE */
#if 0
/* 169-Pin BGA Package */
HW_PINCTRL_MUXSEL5_BANK2_PIN26 | /* Pin 99, EMI_CE1N */
#endif
HW_PINCTRL_MUXSEL5_BANK2_PIN25 | /* Pin 100, EMI_CE0N */
HW_PINCTRL_MUXSEL5_BANK2_PIN24 | /* Pin 97, EMI_CASN */
HW_PINCTRL_MUXSEL5_BANK2_PIN23 | /* Pin 117, EMI_BA1 */
HW_PINCTRL_MUXSEL5_BANK2_PIN22 | /* Pin 116, EMI_BA0 */
HW_PINCTRL_MUXSEL5_BANK2_PIN21 | /* Pin 101, EMI_A12 */
HW_PINCTRL_MUXSEL5_BANK2_PIN20 | /* Pin 102, EMI_A11 */
HW_PINCTRL_MUXSEL5_BANK2_PIN19 | /* Pin 104, EMI_A10 */
HW_PINCTRL_MUXSEL5_BANK2_PIN18 | /* Pin 103, EMI_A09 */
HW_PINCTRL_MUXSEL5_BANK2_PIN17 | /* Pin 106, EMI_A08 */
HW_PINCTRL_MUXSEL5_BANK2_PIN16) /* Pin 105, EMI_A07 */
);
REG_WRITE(HW_PINCTRL_BASE + HW_PINCTRL_MUXSEL6_CLR, (
HW_PINCTRL_MUXSEL6_BANK3_PIN15 | /* Pin 95, EMI_D15 */
HW_PINCTRL_MUXSEL6_BANK3_PIN14 | /* Pin 96, EMI_D14 */
HW_PINCTRL_MUXSEL6_BANK3_PIN13 | /* Pin 94, EMI_D13 */
HW_PINCTRL_MUXSEL6_BANK3_PIN12 | /* Pin 93, EMI_D12 */
HW_PINCTRL_MUXSEL6_BANK3_PIN11 | /* Pin 91, EMI_D11 */
HW_PINCTRL_MUXSEL6_BANK3_PIN10 | /* Pin 89, EMI_D10 */
HW_PINCTRL_MUXSEL6_BANK3_PIN09 | /* Pin 87, EMI_D09 */
HW_PINCTRL_MUXSEL6_BANK3_PIN08 | /* Pin 86, EMI_D08 */
HW_PINCTRL_MUXSEL6_BANK3_PIN07 | /* Pin 85, EMI_D07 */
HW_PINCTRL_MUXSEL6_BANK3_PIN06 | /* Pin 84, EMI_D06 */
HW_PINCTRL_MUXSEL6_BANK3_PIN05 | /* Pin 83, EMI_D05 */
HW_PINCTRL_MUXSEL6_BANK3_PIN04 | /* Pin 82, EMI_D04 */
HW_PINCTRL_MUXSEL6_BANK3_PIN03 | /* Pin 79, EMI_D03 */
HW_PINCTRL_MUXSEL6_BANK3_PIN02 | /* Pin 77, EMI_D02 */
HW_PINCTRL_MUXSEL6_BANK3_PIN01 | /* Pin 76, EMI_D01 */
HW_PINCTRL_MUXSEL6_BANK3_PIN00) /* Pin 75, EMI_D00 */
);
REG_WRITE(HW_PINCTRL_BASE + HW_PINCTRL_MUXSEL7_CLR, (
HW_PINCTRL_MUXSEL7_BANK3_PIN21 | /* Pin 72, EMI_CLKN */
HW_PINCTRL_MUXSEL7_BANK3_PIN20 | /* Pin 70, EMI_CLK */
HW_PINCTRL_MUXSEL7_BANK3_PIN19 | /* Pin 74, EMI_DQS1 */
HW_PINCTRL_MUXSEL7_BANK3_PIN18 | /* Pin 73, EMI_DQS0 */
HW_PINCTRL_MUXSEL7_BANK3_PIN17 | /* Pin 92, EMI_DQM1 */
HW_PINCTRL_MUXSEL7_BANK3_PIN16) /* Pin 81, EMI_DQM0 */
);
return;
}
/*
* Configure EMI pins voltages to 1.8/2.5V operation and drive strength
* to "ma".
*/
void
configure_emi_drive(int ma)
{
uint32_t drive;
/* DRIVE 9 */
drive = REG_READ(HW_PINCTRL_BASE + HW_PINCTRL_DRIVE9);
drive &= ~(
HW_PINCTRL_DRIVE9_BANK2_PIN15_V | /* Pin 108, EMI_A06 */
HW_PINCTRL_DRIVE9_BANK2_PIN15_MA |
HW_PINCTRL_DRIVE9_BANK2_PIN14_V | /* Pin 107, EMI_A05 */
HW_PINCTRL_DRIVE9_BANK2_PIN14_MA |
HW_PINCTRL_DRIVE9_BANK2_PIN13_V | /* Pin 109, EMI_A04 */
HW_PINCTRL_DRIVE9_BANK2_PIN13_MA |
HW_PINCTRL_DRIVE9_BANK2_PIN12_V | /* Pin 110, EMI_A03 */
HW_PINCTRL_DRIVE9_BANK2_PIN12_MA |
HW_PINCTRL_DRIVE9_BANK2_PIN11_V | /* Pin 111, EMI_A02 */
HW_PINCTRL_DRIVE9_BANK2_PIN11_MA |
HW_PINCTRL_DRIVE9_BANK2_PIN10_V | /* Pin 112, EMI_A01 */
HW_PINCTRL_DRIVE9_BANK2_PIN10_MA |
HW_PINCTRL_DRIVE9_BANK2_PIN09_V | /* Pin 113, EMI_A00 */
HW_PINCTRL_DRIVE9_BANK2_PIN09_MA |
HW_PINCTRL_DRIVE9_RSRVD6 | /* Always write zeroes */
HW_PINCTRL_DRIVE9_RSRVD5 |
HW_PINCTRL_DRIVE9_RSRVD4 |
HW_PINCTRL_DRIVE9_RSRVD3 |
HW_PINCTRL_DRIVE9_RSRVD2 |
HW_PINCTRL_DRIVE9_RSRVD1 |
HW_PINCTRL_DRIVE9_RSRVD0
);
drive |= (
__SHIFTIN(ma, HW_PINCTRL_DRIVE9_BANK2_PIN15_MA) | /* EMI_A06 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE9_BANK2_PIN14_MA) | /* EMI_A05 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE9_BANK2_PIN13_MA) | /* EMI_A04 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE9_BANK2_PIN12_MA) | /* EMI_A03 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE9_BANK2_PIN11_MA) | /* EMI_A02 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE9_BANK2_PIN10_MA) | /* EMI_A01 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE9_BANK2_PIN09_MA) /* EMI_A00 */
);
REG_WRITE(HW_PINCTRL_BASE + HW_PINCTRL_DRIVE9, drive);
/* DRIVE 10 */
drive = REG_READ(HW_PINCTRL_BASE + HW_PINCTRL_DRIVE10);
drive &= ~(
HW_PINCTRL_DRIVE10_BANK2_PIN23_V | /* Pin 117, EMI_BA1 */
HW_PINCTRL_DRIVE10_BANK2_PIN23_MA |
HW_PINCTRL_DRIVE10_BANK2_PIN22_V | /* Pin 116, EMI_BA0 */
HW_PINCTRL_DRIVE10_BANK2_PIN22_MA |
HW_PINCTRL_DRIVE10_BANK2_PIN21_V | /* Pin 101, EMI_A12 */
HW_PINCTRL_DRIVE10_BANK2_PIN21_MA |
HW_PINCTRL_DRIVE10_BANK2_PIN20_V | /* Pin 102, EMI_A11 */
HW_PINCTRL_DRIVE10_BANK2_PIN20_MA |
HW_PINCTRL_DRIVE10_BANK2_PIN19_V | /* Pin 104, EMI_A10 */
HW_PINCTRL_DRIVE10_BANK2_PIN19_MA |
HW_PINCTRL_DRIVE10_BANK2_PIN18_V | /* Pin 103, EMI_A09 */
HW_PINCTRL_DRIVE10_BANK2_PIN18_MA |
HW_PINCTRL_DRIVE10_BANK2_PIN17_V | /* Pin 106, EMI_A08 */
HW_PINCTRL_DRIVE10_BANK2_PIN17_MA |
HW_PINCTRL_DRIVE10_BANK2_PIN16_V | /* Pin 105, EMI_A07 */
HW_PINCTRL_DRIVE10_BANK2_PIN16_MA |
HW_PINCTRL_DRIVE10_RSRVD6 | /* Always write zeroes */
HW_PINCTRL_DRIVE10_RSRVD5 |
HW_PINCTRL_DRIVE10_RSRVD4 |
HW_PINCTRL_DRIVE10_RSRVD3 |
HW_PINCTRL_DRIVE10_RSRVD2 |
HW_PINCTRL_DRIVE10_RSRVD1 |
HW_PINCTRL_DRIVE10_RSRVD0
);
drive |= (
__SHIFTIN(ma, HW_PINCTRL_DRIVE10_BANK2_PIN23_MA) | /* EMI_BA1 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE10_BANK2_PIN22_MA) | /* EMI_BA0 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE10_BANK2_PIN21_MA) | /* EMI_A12 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE10_BANK2_PIN20_MA) | /* EMI_A11 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE10_BANK2_PIN19_MA) | /* EMI_A10 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE10_BANK2_PIN18_MA) | /* EMI_A09 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE10_BANK2_PIN17_MA) | /* EMI_A08 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE10_BANK2_PIN16_MA) /* EMI_A07 */
);
REG_WRITE(HW_PINCTRL_BASE + HW_PINCTRL_DRIVE10, drive);
/* DRIVE 11 */
drive = REG_READ(HW_PINCTRL_BASE + HW_PINCTRL_DRIVE11);
drive &= ~(
HW_PINCTRL_DRIVE11_BANK2_PIN31_V | /* Pin 114, EMI_WEN */
HW_PINCTRL_DRIVE11_BANK2_PIN31_MA |
HW_PINCTRL_DRIVE11_BANK2_PIN30_V | /* Pin 98, EMI_RASN */
HW_PINCTRL_DRIVE11_BANK2_PIN30_MA |
HW_PINCTRL_DRIVE11_BANK2_PIN29_V | /* Pin 115, EMI_CKE */
HW_PINCTRL_DRIVE11_BANK2_PIN29_MA |
#if 0
/* 169-Pin BGA Package */
HW_PINCTRL_DRIVE11_BANK2_PIN26_V | /* Pin 99, EMI_CE1N */
HW_PINCTRL_DRIVE11_BANK2_PIN26_MA |
#endif
HW_PINCTRL_DRIVE11_BANK2_PIN25_V | /* Pin 100, EMI_CE0N */
HW_PINCTRL_DRIVE11_BANK2_PIN25_MA |
HW_PINCTRL_DRIVE11_BANK2_PIN24_V | /* Pin 97, EMI_CASN */
HW_PINCTRL_DRIVE11_BANK2_PIN24_MA |
HW_PINCTRL_DRIVE11_RSRVD6 | /* Always write zeroes */
HW_PINCTRL_DRIVE11_RSRVD5 |
HW_PINCTRL_DRIVE11_RSRVD4 |
HW_PINCTRL_DRIVE11_RSRVD3 |
HW_PINCTRL_DRIVE11_RSRVD2 |
HW_PINCTRL_DRIVE11_RSRVD1 |
HW_PINCTRL_DRIVE11_RSRVD0
);
drive |= (
__SHIFTIN(ma, HW_PINCTRL_DRIVE11_BANK2_PIN31_MA) | /* EMI_WEN */
__SHIFTIN(ma, HW_PINCTRL_DRIVE11_BANK2_PIN30_MA) | /* EMI_RASN */
__SHIFTIN(ma, HW_PINCTRL_DRIVE11_BANK2_PIN29_MA) | /* EMI_CKE */
#if 0 /* 169-Pin BGA Package */
__SHIFTIN(ma, HW_PINCTRL_DRIVE11_BANK2_PIN26_MA) | /* EMI_CE1N */
#endif
__SHIFTIN(ma, HW_PINCTRL_DRIVE11_BANK2_PIN25_MA) | /* EMI_CE0N */
__SHIFTIN(ma, HW_PINCTRL_DRIVE11_BANK2_PIN24_MA) /* EMI_CASN */
);
REG_WRITE(HW_PINCTRL_BASE + HW_PINCTRL_DRIVE11, drive);
/* DRIVE 12 */
drive = REG_READ(HW_PINCTRL_BASE + HW_PINCTRL_DRIVE12);
drive &= ~(
HW_PINCTRL_DRIVE12_BANK3_PIN07_V | /* Pin 85, EMI_D07 */
HW_PINCTRL_DRIVE12_BANK3_PIN07_MA |
HW_PINCTRL_DRIVE12_BANK3_PIN06_V | /* Pin 84, EMI_D06 */
HW_PINCTRL_DRIVE12_BANK3_PIN06_MA |
HW_PINCTRL_DRIVE12_BANK3_PIN05_V | /* Pin 83, EMI_D05 */
HW_PINCTRL_DRIVE12_BANK3_PIN05_MA |
HW_PINCTRL_DRIVE12_BANK3_PIN04_V | /* Pin 82, EMI_D04 */
HW_PINCTRL_DRIVE12_BANK3_PIN04_MA |
HW_PINCTRL_DRIVE12_BANK3_PIN03_V | /* Pin 79, EMI_D03 */
HW_PINCTRL_DRIVE12_BANK3_PIN03_MA |
HW_PINCTRL_DRIVE12_BANK3_PIN02_V | /* Pin 77, EMI_D02 */
HW_PINCTRL_DRIVE12_BANK3_PIN02_MA |
HW_PINCTRL_DRIVE12_BANK3_PIN01_V | /* Pin 76, EMI_D01 */
HW_PINCTRL_DRIVE12_BANK3_PIN01_MA |
HW_PINCTRL_DRIVE12_BANK3_PIN00_V | /* Pin 75, EMI_D00 */
HW_PINCTRL_DRIVE12_BANK3_PIN00_MA |
HW_PINCTRL_DRIVE12_RSRVD6 | /* Always write zeroes */
HW_PINCTRL_DRIVE12_RSRVD5 |
HW_PINCTRL_DRIVE12_RSRVD4 |
HW_PINCTRL_DRIVE12_RSRVD3 |
HW_PINCTRL_DRIVE12_RSRVD2 |
HW_PINCTRL_DRIVE12_RSRVD1 |
HW_PINCTRL_DRIVE12_RSRVD0
);
drive |= (
__SHIFTIN(ma, HW_PINCTRL_DRIVE12_BANK3_PIN07_MA) | /* EMI_D07 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE12_BANK3_PIN06_MA) | /* EMI_D06 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE12_BANK3_PIN05_MA) | /* EMI_D05 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE12_BANK3_PIN04_MA) | /* EMI_D04 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE12_BANK3_PIN03_MA) | /* EMI_D03 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE12_BANK3_PIN02_MA) | /* EMI_D02 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE12_BANK3_PIN01_MA) | /* EMI_D01 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE12_BANK3_PIN00_MA) /* EMI_D00 */
);
REG_WRITE(HW_PINCTRL_BASE + HW_PINCTRL_DRIVE12, drive);
/* DRIVE 13 */
drive = REG_READ(HW_PINCTRL_BASE + HW_PINCTRL_DRIVE13);
drive &= ~(
HW_PINCTRL_DRIVE13_BANK3_PIN15_V | /* Pin 95, EMI_D15 */
HW_PINCTRL_DRIVE13_BANK3_PIN15_MA |
HW_PINCTRL_DRIVE13_BANK3_PIN14_V | /* Pin 96, EMI_D14 */
HW_PINCTRL_DRIVE13_BANK3_PIN14_MA |
HW_PINCTRL_DRIVE13_BANK3_PIN13_V | /* Pin 94, EMI_D13 */
HW_PINCTRL_DRIVE13_BANK3_PIN13_MA |
HW_PINCTRL_DRIVE13_BANK3_PIN12_V | /* Pin 93, EMI_D12 */
HW_PINCTRL_DRIVE13_BANK3_PIN12_MA |
HW_PINCTRL_DRIVE13_BANK3_PIN11_V | /* Pin 91, EMI_D11 */
HW_PINCTRL_DRIVE13_BANK3_PIN11_MA |
HW_PINCTRL_DRIVE13_BANK3_PIN10_V | /* Pin 89, EMI_D10 */
HW_PINCTRL_DRIVE13_BANK3_PIN10_MA |
HW_PINCTRL_DRIVE13_BANK3_PIN09_V | /* Pin 87, EMI_D09 */
HW_PINCTRL_DRIVE13_BANK3_PIN09_MA |
HW_PINCTRL_DRIVE13_BANK3_PIN08_V | /* Pin 86, EMI_D08 */
HW_PINCTRL_DRIVE13_BANK3_PIN08_MA |
HW_PINCTRL_DRIVE13_RSRVD6 | /* Always write zeroes */
HW_PINCTRL_DRIVE13_RSRVD5 |
HW_PINCTRL_DRIVE13_RSRVD4 |
HW_PINCTRL_DRIVE13_RSRVD3 |
HW_PINCTRL_DRIVE13_RSRVD2 |
HW_PINCTRL_DRIVE13_RSRVD1 |
HW_PINCTRL_DRIVE13_RSRVD0
);
drive |= (
__SHIFTIN(ma, HW_PINCTRL_DRIVE13_BANK3_PIN15_MA) | /* EMI_D15 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE13_BANK3_PIN14_MA) | /* EMI_D14 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE13_BANK3_PIN13_MA) | /* EMI_D13 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE13_BANK3_PIN12_MA) | /* EMI_D12 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE13_BANK3_PIN11_MA) | /* EMI_D11 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE13_BANK3_PIN10_MA) | /* EMI_D10 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE13_BANK3_PIN09_MA) | /* EMI_D09 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE13_BANK3_PIN08_MA) /* EMI_D08 */
);
REG_WRITE(HW_PINCTRL_BASE + HW_PINCTRL_DRIVE13, drive);
/* DRIVE 14 */
drive = REG_READ(HW_PINCTRL_BASE + HW_PINCTRL_DRIVE14);
drive &= ~(
HW_PINCTRL_DRIVE14_BANK3_PIN21_V | /* Pin 72, EMI_CLKN */
HW_PINCTRL_DRIVE14_BANK3_PIN21_MA |
HW_PINCTRL_DRIVE14_BANK3_PIN20_V | /* Pin 70, EMI_CLK */
HW_PINCTRL_DRIVE14_BANK3_PIN20_MA |
HW_PINCTRL_DRIVE14_BANK3_PIN19_V | /* Pin 74, EMI_DQS1 */
HW_PINCTRL_DRIVE14_BANK3_PIN19_MA |
HW_PINCTRL_DRIVE14_BANK3_PIN18_V | /* Pin 73, EMI_DQS0 */
HW_PINCTRL_DRIVE14_BANK3_PIN18_MA |
HW_PINCTRL_DRIVE14_BANK3_PIN17_V | /* Pin 92, EMI_DQM1 */
HW_PINCTRL_DRIVE14_BANK3_PIN17_MA |
HW_PINCTRL_DRIVE14_BANK3_PIN16_V | /* Pin 81, EMI_DQM0 */
HW_PINCTRL_DRIVE14_BANK3_PIN16_MA |
HW_PINCTRL_DRIVE14_RSRVD6 | /* Always write zeroes */
HW_PINCTRL_DRIVE14_RSRVD5 |
HW_PINCTRL_DRIVE14_RSRVD4 |
HW_PINCTRL_DRIVE14_RSRVD3 |
HW_PINCTRL_DRIVE14_RSRVD2 |
HW_PINCTRL_DRIVE14_RSRVD1 |
HW_PINCTRL_DRIVE14_RSRVD0
);
drive |= (
__SHIFTIN(ma, HW_PINCTRL_DRIVE14_BANK3_PIN21_MA) | /* EMI_CLKN */
__SHIFTIN(ma, HW_PINCTRL_DRIVE14_BANK3_PIN20_MA) | /* EMI_CLK */
__SHIFTIN(ma, HW_PINCTRL_DRIVE14_BANK3_PIN19_MA) | /* EMI_DQS1 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE14_BANK3_PIN18_MA) | /* EMI_DQS0 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE14_BANK3_PIN17_MA) | /* EMI_DQM1 */
__SHIFTIN(ma, HW_PINCTRL_DRIVE14_BANK3_PIN16_MA) /* EMI_DQM0 */
);
REG_WRITE(HW_PINCTRL_BASE + HW_PINCTRL_DRIVE14, drive);
return;
}
/*
* Disable internal gate keepers on EMI pins.
*/
void
disable_emi_padkeepers(void)
{
REG_WRITE(HW_PINCTRL_BASE + HW_PINCTRL_PULL3_SET, (
HW_PINCTRL_PULL3_BANK3_PIN17 | /* EMI_DQM1 */
HW_PINCTRL_PULL3_BANK3_PIN16 | /* EMI_DQM0 */
HW_PINCTRL_PULL3_BANK3_PIN15 | /* EMI_D15 */
HW_PINCTRL_PULL3_BANK3_PIN14 | /* EMI_D14 */
HW_PINCTRL_PULL3_BANK3_PIN13 | /* EMI_D13 */
HW_PINCTRL_PULL3_BANK3_PIN12 | /* EMI_D12 */
HW_PINCTRL_PULL3_BANK3_PIN11 | /* EMI_D11 */
HW_PINCTRL_PULL3_BANK3_PIN10 | /* EMI_D10 */
HW_PINCTRL_PULL3_BANK3_PIN09 | /* EMI_D09 */
HW_PINCTRL_PULL3_BANK3_PIN08 | /* EMI_D08 */
HW_PINCTRL_PULL3_BANK3_PIN07 | /* EMI_D07 */
HW_PINCTRL_PULL3_BANK3_PIN06 | /* EMI_D06 */
HW_PINCTRL_PULL3_BANK3_PIN05 | /* EMI_D05 */
HW_PINCTRL_PULL3_BANK3_PIN04 | /* EMI_D04 */
HW_PINCTRL_PULL3_BANK3_PIN03 | /* EMI_D03 */
HW_PINCTRL_PULL3_BANK3_PIN02 | /* EMI_D02 */
HW_PINCTRL_PULL3_BANK3_PIN01 | /* EMI_D01 */
HW_PINCTRL_PULL3_BANK3_PIN00) /* EMI_D00 */
);
return;
}
/*
* Configure external SSP pins to be used for SD/MMC.
*/
void
configure_ssp_mux(void)
{
REG_WRITE(HW_PINCTRL_BASE + HW_PINCTRL_MUXSEL4_CLR, (
HW_PINCTRL_MUXSEL4_BANK2_PIN00 | /* Pin 121, SSP1_CMD */
HW_PINCTRL_MUXSEL4_BANK2_PIN02 | /* Pin 122, SSP1_DATA0 */
HW_PINCTRL_MUXSEL4_BANK2_PIN03 | /* Pin 123, SSP1_DATA1 */
HW_PINCTRL_MUXSEL4_BANK2_PIN04 | /* Pin 124, SSP1_DATA2 */
HW_PINCTRL_MUXSEL4_BANK2_PIN05 | /* Pin 125, SSP1_DATA3 */
HW_PINCTRL_MUXSEL4_BANK2_PIN06) /* Pin 127, SSP1_SCK */
);
return;
}
/*
* Configure SSP pins drive strength to "ma".
* Out of reset, all non-EMI pins are configured as 3.3 V.
*/
void
configure_ssp_drive(int ma)
{
uint32_t reg = REG_READ(HW_PINCTRL_BASE + HW_PINCTRL_DRIVE8);
reg &= ~(
HW_PINCTRL_DRIVE8_BANK2_PIN06_MA | /* Pin 127, SSP1_SCK */
HW_PINCTRL_DRIVE8_BANK2_PIN05_MA | /* Pin 125, SSP1_DATA3 */
HW_PINCTRL_DRIVE8_BANK2_PIN04_MA | /* Pin 124, SSP1_DATA2 */
HW_PINCTRL_DRIVE8_BANK2_PIN03_MA | /* Pin 123, SSP1_DATA1 */
HW_PINCTRL_DRIVE8_BANK2_PIN02_MA | /* Pin 122, SSP1_DATA0 */
HW_PINCTRL_DRIVE8_BANK2_PIN00_MA /* Pin 121, SSP1_CMD */
);
reg |= __SHIFTIN(ma, HW_PINCTRL_DRIVE8_BANK2_PIN06_MA) |
__SHIFTIN(ma, HW_PINCTRL_DRIVE8_BANK2_PIN05_MA) |
__SHIFTIN(ma, HW_PINCTRL_DRIVE8_BANK2_PIN04_MA) |
__SHIFTIN(ma, HW_PINCTRL_DRIVE8_BANK2_PIN03_MA) |
__SHIFTIN(ma, HW_PINCTRL_DRIVE8_BANK2_PIN02_MA) |
__SHIFTIN(ma, HW_PINCTRL_DRIVE8_BANK2_PIN00_MA
);
REG_WRITE(HW_PINCTRL_BASE + HW_PINCTRL_DRIVE8, reg);
return;
}
/*
* Configure SSP pull ups.
*/
void
configure_ssp_pullups(void)
{
/* Disable pull ups for SSP and let HW take care of them. */
// REG_WRITE(HW_PINCTRL_BASE + HW_PINCTRL_PULL2_CLR, (
// HW_PINCTRL_PULL2_BANK2_PIN05 |/* Pin 125, SSP1_DATA3 */
// HW_PINCTRL_PULL2_BANK2_PIN04 | /* Pin 124, SSP1_DATA2 */
// HW_PINCTRL_PULL2_BANK2_PIN03 | /* Pin 123, SSP1_DATA1 */
// HW_PINCTRL_PULL2_BANK2_PIN02 | /* Pin 122, SSP1_DATA0 */
// HW_PINCTRL_PULL2_BANK2_PIN00 /* Pin 121, SSP1_CMD */
// ));
REG_WRITE(HW_PINCTRL_BASE + HW_PINCTRL_PULL2_SET, (
HW_PINCTRL_PULL2_BANK2_PIN05 |/* Pin 125, SSP1_DATA3 */
HW_PINCTRL_PULL2_BANK2_PIN04 | /* Pin 124, SSP1_DATA2 */
HW_PINCTRL_PULL2_BANK2_PIN03 | /* Pin 123, SSP1_DATA1 */
HW_PINCTRL_PULL2_BANK2_PIN02 | /* Pin 122, SSP1_DATA0 */
HW_PINCTRL_PULL2_BANK2_PIN00 /* Pin 121, SSP1_CMD */
));
return;
}

View File

@ -0,0 +1,579 @@
/* $Id: power_prep.c,v 1.1 2012/11/20 19:08:46 jkunz Exp $ */
/*
* Copyright (c) 2012 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Petri Laakso.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#include <arm/imx/imx23_powerreg.h>
#include <lib/libsa/stand.h>
#include "common.h"
void charge_4p2_capacitance(void);
void enable_4p2_linreg(void);
void enable_dcdc(void);
void enable_vbusvalid_comparator(void);
void set_targets(void);
void dcdc4p2_enable_dcdc(void);
void p5vctrl_enable_dcdc(void);
void enable_vddmem(void);
/*
* Power rail voltage targets, brownout levels and linear regulator
* offsets from the target.
*
* Supply Target BO LinReg offset
* ------------------------------------------
* VDDD 1.550 V 1.450 V -25 mV
* VDDA 1.750 V 1.575 V -25 mV
* VDDIO 3.100 V 2.925 V -25 mV
* VDDMEM 2.500 V <na> <na>
*
* BO = Brownout level below target.
*/
#define VDDD_TARGET 0x1e
#define VDDD_BO_OFFSET 0x4
#define VDDD_LINREG_OFFSET 0x02
#define VDDA_TARGET 0x0A
#define VDDA_BO_OFFSET 0x07
#define VDDA_LINREG_OFFSET 0x02
#define VDDIO_TARGET 0x0C
#define VDDIO_BO_OFFSET 0x07
#define VDDIO_LINREG_OFFSET 0x02
#define VDDMEM_TARGET 0x10
/*
* Threshold voltage for the VBUSVALID comparator.
* Always make sure that the VDD5V voltage level is higher.
*/
#define VBUSVALID_TRSH 0x02 /* 4.1 V */
/* Limits for BATT charger + 4P2 current */
#define P4P2_ILIMIT_MIN 0x01 /* 10 mA */
#define P4P2_ILIMIT_MAX 0x3f /* 780 mA */
/*
* Trip point for the comparison between the DCDC_4P2 and BATTERY pin.
* If this voltage comparation is true then 5 V originated power will supply
* the DCDC. Otherwise battery will be used.
*/
#define DCDC4P2_CMPTRIP 0x00 /* DCDC_4P2 pin > 0.85 * BATTERY pin */
/*
* Adjust the behavior of the DCDC and 4.2 V circuit.
* Two MSBs control the VDD4P2 brownout below the DCDC4P2_TRG before the
* regulation circuit steals battery charge. Two LSBs control which power
* source is selected by the DCDC.
*/
#define DCDC4P2_DROPOUT_CTRL_BO_200 0x0C
#define DCDC4P2_DROPOUT_CTRL_BO_100 0x08
#define DCDC4P2_DROPOUT_CTRL_BO_050 0x04
#define DCDC4P2_DROPOUT_CTRL_BO_025 0x00
#define DCDC4P2_DROPOUT_CTRL_SEL_4P2 0x00 /* Don't use battery at all. */
#define DCDC4P2_DROPOUT_CTRL_SEL_BATT_IF_GT_4P2 0x01 /* BATT if 4P2 < BATT */
#define DCDC4P2_DROPOUT_CTRL_SEL_HIGHER 0x02 /* Selects which ever is
* higher. */
#define DCDC4P2_DROPOUT_CTRL (DCDC4P2_DROPOUT_CTRL_BO_200 |\
DCDC4P2_DROPOUT_CTRL_SEL_4P2)
/*
* Prepare system for a 5 V operation.
*
* The system uses inefficient linear regulators as a power source after boot.
* This code enables the use of more energy efficient DC-DC converter as a
* power source.
*/
int
power_prep(void)
{
/* Enable clocks to the power block */
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR, HW_POWER_CTRL_CLKGATE);
set_targets();
enable_vbusvalid_comparator();
enable_4p2_linreg();
charge_4p2_capacitance();
enable_dcdc();
enable_vddmem();
return 0;
}
/*
* Set switching converter voltage targets, brownout levels and linear
* regulator output offsets.
*/
void
set_targets(void)
{
uint32_t vddctrl;
/* VDDD */
vddctrl = REG_READ(HW_POWER_BASE + HW_POWER_VDDDCTRL);
vddctrl &= ~(HW_POWER_VDDDCTRL_LINREG_OFFSET |
HW_POWER_VDDDCTRL_BO_OFFSET |
HW_POWER_VDDDCTRL_TRG);
vddctrl |=
__SHIFTIN(VDDD_LINREG_OFFSET, HW_POWER_VDDDCTRL_LINREG_OFFSET) |
__SHIFTIN(VDDD_BO_OFFSET, HW_POWER_VDDDCTRL_BO_OFFSET) |
__SHIFTIN(VDDD_TARGET, HW_POWER_VDDDCTRL_TRG);
REG_WRITE(HW_POWER_BASE + HW_POWER_VDDDCTRL, vddctrl);
/* VDDA */
vddctrl = REG_READ(HW_POWER_BASE + HW_POWER_VDDACTRL);
vddctrl &= ~(HW_POWER_VDDACTRL_LINREG_OFFSET |
HW_POWER_VDDACTRL_BO_OFFSET |
HW_POWER_VDDACTRL_TRG);
vddctrl |=
__SHIFTIN(VDDA_LINREG_OFFSET, HW_POWER_VDDACTRL_LINREG_OFFSET) |
__SHIFTIN(VDDA_BO_OFFSET, HW_POWER_VDDACTRL_BO_OFFSET) |
__SHIFTIN(VDDA_TARGET, HW_POWER_VDDACTRL_TRG);
REG_WRITE(HW_POWER_BASE + HW_POWER_VDDACTRL, vddctrl);
/* VDDIO */
vddctrl = REG_READ(HW_POWER_BASE + HW_POWER_VDDIOCTRL);
vddctrl &= ~(HW_POWER_VDDIOCTRL_LINREG_OFFSET |
HW_POWER_VDDIOCTRL_BO_OFFSET |
HW_POWER_VDDIOCTRL_TRG);
vddctrl |=
__SHIFTIN(VDDIO_LINREG_OFFSET, HW_POWER_VDDACTRL_LINREG_OFFSET) |
__SHIFTIN(VDDIO_BO_OFFSET, HW_POWER_VDDACTRL_BO_OFFSET) |
__SHIFTIN(VDDIO_TARGET, HW_POWER_VDDACTRL_TRG);
REG_WRITE(HW_POWER_BASE + HW_POWER_VDDIOCTRL, vddctrl);
/* VDDMEM */
vddctrl = REG_READ(HW_POWER_BASE + HW_POWER_VDDMEMCTRL);
vddctrl &= ~(HW_POWER_VDDMEMCTRL_TRG);
vddctrl |= __SHIFTIN(VDDMEM_TARGET, HW_POWER_VDDMEMCTRL_TRG);
REG_WRITE(HW_POWER_BASE + HW_POWER_VDDMEMCTRL, vddctrl);
return;
}
/*
* VBUSVALID comparator is accurate method to determine the presence of 5 V.
* Turn on the comparator, set its voltage treshold and instruct DC-DC to
* use it.
*/
void
enable_vbusvalid_comparator()
{
uint32_t p5vctrl;
/*
* Disable 5 V brownout detection temporarily because setting
* VBUSVALID_5VDETECT can cause false brownout.
*/
REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_CLR,
HW_POWER_5VCTRL_PWDN_5VBRNOUT);
p5vctrl = REG_READ(HW_POWER_BASE + HW_POWER_5VCTRL);
p5vctrl &= ~HW_POWER_5VCTRL_VBUSVALID_TRSH;
p5vctrl |=
/* Turn on VBUS comparators. */
(HW_POWER_5VCTRL_PWRUP_VBUS_CMPS |
/* Set treshold for VBUSVALID comparator. */
__SHIFTIN(VBUSVALID_TRSH, HW_POWER_5VCTRL_VBUSVALID_TRSH) |
/* Set DC-DC to use VBUSVALID comparator. */
HW_POWER_5VCTRL_VBUSVALID_5VDETECT);
REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL, p5vctrl);
/* Enable temporarily disabled 5 V brownout detection. */
REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_SET,
HW_POWER_5VCTRL_PWDN_5VBRNOUT);
return;
}
/*
* Enable 4P2 linear regulator.
*/
void
enable_4p2_linreg(void)
{
uint32_t dcdc4p2;
uint32_t p5vctrl;
dcdc4p2 = REG_READ(HW_POWER_BASE + HW_POWER_DCDC4P2);
/* Set the 4P2 target to 4.2 V and BO to 3.6V by clearing TRG and BO
* field. */
dcdc4p2 &= ~(HW_POWER_DCDC4P2_TRG | HW_POWER_DCDC4P2_BO);
/* Enable the 4P2 circuitry to control the LinReg. */
dcdc4p2 |= HW_POWER_DCDC4P2_ENABLE_4P2;
REG_WRITE(HW_POWER_BASE + HW_POWER_DCDC4P2, dcdc4p2);
/* The 4P2 LinReg needs a static load to operate correctly. Since the
* DC-DC is not yet loading the LinReg, another load must be used. */
REG_WRITE(HW_POWER_BASE + HW_POWER_CHARGE_SET,
HW_POWER_CHARGE_ENABLE_LOAD);
p5vctrl = REG_READ(HW_POWER_BASE + HW_POWER_5VCTRL);
p5vctrl &= ~(HW_POWER_5VCTRL_CHARGE_4P2_ILIMIT |
/* Power on the 4P2 LinReg. ON = 0x0, OFF = 0x1 */
HW_POWER_5VCTRL_PWD_CHARGE_4P2);
p5vctrl |=
/* Provide an initial current limit for the 4P2 LinReg with the
* smallest value possible. */
__SHIFTIN(P4P2_ILIMIT_MIN, HW_POWER_5VCTRL_CHARGE_4P2_ILIMIT);
REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL, p5vctrl);
/* Ungate the path from 4P2 LinReg to DC-DC. */
dcdc4p2_enable_dcdc();
return;
}
/*
* There is capacitor on the 4P2 output which must be charged before powering
* on the 4P2 linear regulator to avoid brownouts on the 5 V source.
* Charging is done by slowly increasing current limit until it reaches
* P4P2_ILIMIT_MAX.
*/
void
charge_4p2_capacitance(void)
{
uint32_t ilimit;
uint32_t p5vctrl;
p5vctrl = REG_READ(HW_POWER_BASE + HW_POWER_5VCTRL);
ilimit = __SHIFTOUT(p5vctrl, HW_POWER_5VCTRL_CHARGE_4P2_ILIMIT);
/* Increment current limit slowly. */
while (ilimit < P4P2_ILIMIT_MAX) {
ilimit++;
p5vctrl &= ~(HW_POWER_5VCTRL_CHARGE_4P2_ILIMIT);
p5vctrl |= __SHIFTIN(ilimit, HW_POWER_5VCTRL_CHARGE_4P2_ILIMIT);
REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL, p5vctrl);
delay_us(10000);
}
return;
}
/*
* Enable DCDC to use 4P2 regulator and set its power source selection logic.
*/
void
enable_dcdc(void)
{
uint32_t dcdc4p2;
uint32_t vddctrl;
dcdc4p2 = REG_READ(HW_POWER_BASE + HW_POWER_DCDC4P2);
dcdc4p2 &= ~(HW_POWER_DCDC4P2_CMPTRIP | HW_POWER_DCDC4P2_DROPOUT_CTRL);
/* Comparison between the DCDC_4P2 pin and BATTERY pin to choose which
* will supply the DCDC. */
dcdc4p2 |= __SHIFTIN(DCDC4P2_CMPTRIP, HW_POWER_DCDC4P2_CMPTRIP);
/* DC-DC brownout and select logic. */
dcdc4p2 |= __SHIFTIN(DCDC4P2_DROPOUT_CTRL,
HW_POWER_DCDC4P2_DROPOUT_CTRL);
REG_WRITE(HW_POWER_BASE + HW_POWER_DCDC4P2, dcdc4p2);
/* Disable the automatic DC-DC startup when 5 V is lost (it is on
* already) */
REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_CLR,
HW_POWER_5VCTRL_DCDC_XFER);
p5vctrl_enable_dcdc();
/* Enable switching converter outputs and disable linear regulators
* for VDDD, VDDIO and VDDA. */
vddctrl = REG_READ(HW_POWER_BASE + HW_POWER_VDDDCTRL);
vddctrl &= ~(HW_POWER_VDDDCTRL_DISABLE_FET |
HW_POWER_VDDDCTRL_ENABLE_LINREG);
REG_WRITE(HW_POWER_BASE + HW_POWER_VDDDCTRL, vddctrl);
vddctrl = REG_READ(HW_POWER_BASE + HW_POWER_VDDIOCTRL);
vddctrl &= ~HW_POWER_VDDIOCTRL_DISABLE_FET;
REG_WRITE(HW_POWER_BASE + HW_POWER_VDDIOCTRL, vddctrl);
vddctrl = REG_READ(HW_POWER_BASE + HW_POWER_VDDACTRL);
vddctrl &= ~(HW_POWER_VDDACTRL_DISABLE_FET |
HW_POWER_VDDACTRL_ENABLE_LINREG);
REG_WRITE(HW_POWER_BASE + HW_POWER_VDDACTRL, vddctrl);
/* The 4P2 LinReg needs a static load to operate correctly. Since the
* DC-DC is already running we can remove extra 100 ohm load enabled
* before. */
REG_WRITE(HW_POWER_BASE + HW_POWER_CHARGE_CLR,
HW_POWER_CHARGE_ENABLE_LOAD);
return;
}
/*
* DCDC4P2 DCDC enable sequence according to errata #5837
*/
void
dcdc4p2_enable_dcdc(void)
{
uint32_t dcdc4p2;
uint32_t p5vctrl;
uint32_t p5vctrl_saved;
uint32_t pctrl;
uint32_t pctrl_saved;
pctrl_saved = REG_READ(HW_POWER_BASE + HW_POWER_CTRL);
p5vctrl_saved = REG_READ(HW_POWER_BASE + HW_POWER_5VCTRL);
/* Disable the power rail brownout interrupts. */
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
(HW_POWER_CTRL_ENIRQ_VDDA_BO |
HW_POWER_CTRL_ENIRQ_VDDD_BO |
HW_POWER_CTRL_ENIRQ_VDDIO_BO));
/* Set the HW_POWER_5VCTRL PWRUP_VBUS_CMPS bit (may already be set) */
REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_SET,
HW_POWER_5VCTRL_PWRUP_VBUS_CMPS);
/* Set the HW_POWER_5VCTRL VBUSVALID_5VDETECT bit to 0 */
REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_CLR,
HW_POWER_5VCTRL_VBUSVALID_5VDETECT);
/* Set the HW_POWER_5VCTRL VBUSVALID_TRSH to 0x0 (2.9 V) */
REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_CLR,
HW_POWER_5VCTRL_VBUSVALID_TRSH);
/* Disable VBUSDROOP status and interrupt. */
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
(HW_POWER_CTRL_VDD5V_DROOP_IRQ | HW_POWER_CTRL_ENIRQ_VDD5V_DROOP));
/* Set the ENABLE_DCDC bit in HW_POWER_DCDC4P2. */
dcdc4p2 = REG_READ(HW_POWER_BASE + HW_POWER_DCDC4P2);
dcdc4p2 |= HW_POWER_DCDC4P2_ENABLE_DCDC;
REG_WRITE(HW_POWER_BASE + HW_POWER_DCDC4P2, dcdc4p2);
delay_us(100);
pctrl = REG_READ(HW_POWER_BASE + HW_POWER_CTRL);
/* VBUSVALID_IRQ is set. */
if (__SHIFTOUT(pctrl, HW_POWER_CTRL_VBUSVALID_IRQ)) {
/* Set and clear the PWD_CHARGE_4P2 bit to repower on the 4P2
* regulator because it is automatically shut off on a
* VBUSVALID false condition. */
REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_SET,
HW_POWER_5VCTRL_PWD_CHARGE_4P2);
REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_CLR,
HW_POWER_5VCTRL_PWD_CHARGE_4P2);
/* Ramp up the CHARGE_4P2_ILIMIT value at this point. */
charge_4p2_capacitance();
}
/* Restore modified bits back to HW_POWER_CTRL. */
if (pctrl_saved & HW_POWER_CTRL_ENIRQ_VDDA_BO)
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_SET,
HW_POWER_CTRL_ENIRQ_VDDA_BO);
else
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
HW_POWER_CTRL_ENIRQ_VDDA_BO);
if (pctrl_saved & HW_POWER_CTRL_ENIRQ_VDDD_BO)
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_SET,
HW_POWER_CTRL_ENIRQ_VDDD_BO);
else
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
HW_POWER_CTRL_ENIRQ_VDDD_BO);
if (pctrl_saved & HW_POWER_CTRL_ENIRQ_VDDIO_BO)
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_SET,
HW_POWER_CTRL_ENIRQ_VDDIO_BO);
else
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
HW_POWER_CTRL_ENIRQ_VDDIO_BO);
if (pctrl_saved & HW_POWER_CTRL_VDD5V_DROOP_IRQ)
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_SET,
HW_POWER_CTRL_VDD5V_DROOP_IRQ);
else
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
HW_POWER_CTRL_VDD5V_DROOP_IRQ);
if (pctrl_saved & HW_POWER_CTRL_ENIRQ_VDD5V_DROOP)
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_SET,
HW_POWER_CTRL_ENIRQ_VDD5V_DROOP);
else
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
HW_POWER_CTRL_ENIRQ_VDD5V_DROOP);
/* Restore modified bits back to HW_POWER_5VCTRL. */
p5vctrl = REG_READ(HW_POWER_BASE + HW_POWER_5VCTRL);
p5vctrl &= ~(HW_POWER_5VCTRL_PWRUP_VBUS_CMPS |
HW_POWER_5VCTRL_VBUSVALID_5VDETECT |
HW_POWER_5VCTRL_VBUSVALID_TRSH);
p5vctrl |= __SHIFTOUT(p5vctrl_saved, HW_POWER_5VCTRL_VBUSVALID_TRSH) |
(p5vctrl_saved & HW_POWER_5VCTRL_PWRUP_VBUS_CMPS) |
(p5vctrl_saved & HW_POWER_5VCTRL_VBUSVALID_5VDETECT);
REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL, p5vctrl);
return;
}
/*
* 5VCTRL DCDC enable sequence according to errata #5837
*/
void
p5vctrl_enable_dcdc(void)
{
uint32_t p5vctrl;
uint32_t p5vctrl_saved;
uint32_t pctrl;
uint32_t pctrl_saved;
pctrl_saved = REG_READ(HW_POWER_BASE + HW_POWER_CTRL);
p5vctrl_saved = REG_READ(HW_POWER_BASE + HW_POWER_5VCTRL);
/* Disable the power rail brownout interrupts. */
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
HW_POWER_CTRL_ENIRQ_VDDA_BO |
HW_POWER_CTRL_ENIRQ_VDDD_BO |
HW_POWER_CTRL_ENIRQ_VDDIO_BO);
/* Set the HW_POWER_5VCTRL PWRUP_VBUS_CMPS bit (may already be set) */
REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_SET,
HW_POWER_5VCTRL_PWRUP_VBUS_CMPS);
/* Set the HW_POWER_5VCTRL VBUSVALID_5VDETECT bit to 1 */
REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_SET,
HW_POWER_5VCTRL_VBUSVALID_5VDETECT);
/* Set the HW_POWER_5VCTRL VBUSVALID_TRSH to 0x0 (2.9 V) */
REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_CLR,
HW_POWER_5VCTRL_VBUSVALID_TRSH);
/* Disable VBUSDROOP status and interrupt. */
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
(HW_POWER_CTRL_VDD5V_DROOP_IRQ | HW_POWER_CTRL_ENIRQ_VDD5V_DROOP));
/* Work over errata #2816 by disabling 5 V brownout while modifying
* ENABLE_DCDC. */
REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_CLR,
HW_POWER_5VCTRL_PWDN_5VBRNOUT);
/* Set the ENABLE_DCDC bit in HW_POWER_5VCTRL. */
REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_SET,
HW_POWER_5VCTRL_ENABLE_DCDC);
REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL_SET,
HW_POWER_5VCTRL_PWDN_5VBRNOUT);
delay_us(100);
pctrl = REG_READ(HW_POWER_BASE + HW_POWER_CTRL);
/* VBUSVALID_IRQ is set. */
if (__SHIFTOUT(pctrl, HW_POWER_CTRL_VBUSVALID_IRQ)) {
/* repeat the sequence for enabling the 4P2 regulator and DCDC
* from 4P2. */
enable_4p2_linreg();
}
/* Restore modified bits back to HW_POWER_CTRL. */
if (pctrl_saved & HW_POWER_CTRL_ENIRQ_VDDA_BO)
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_SET,
HW_POWER_CTRL_ENIRQ_VDDA_BO);
else
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
HW_POWER_CTRL_ENIRQ_VDDA_BO);
if (pctrl_saved & HW_POWER_CTRL_ENIRQ_VDDD_BO)
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_SET,
HW_POWER_CTRL_ENIRQ_VDDD_BO);
else
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
HW_POWER_CTRL_ENIRQ_VDDD_BO);
if (pctrl_saved & HW_POWER_CTRL_ENIRQ_VDDIO_BO)
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_SET,
HW_POWER_CTRL_ENIRQ_VDDIO_BO);
else
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
HW_POWER_CTRL_ENIRQ_VDDIO_BO);
if (pctrl_saved & HW_POWER_CTRL_VDD5V_DROOP_IRQ)
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_SET,
HW_POWER_CTRL_VDD5V_DROOP_IRQ);
else
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
HW_POWER_CTRL_VDD5V_DROOP_IRQ);
if (pctrl_saved & HW_POWER_CTRL_ENIRQ_VDD5V_DROOP)
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_SET,
HW_POWER_CTRL_ENIRQ_VDD5V_DROOP);
else
REG_WRITE(HW_POWER_BASE + HW_POWER_CTRL_CLR,
HW_POWER_CTRL_ENIRQ_VDD5V_DROOP);
/* Restore modified bits back to HW_POWER_5VCTRL. */
p5vctrl = REG_READ(HW_POWER_BASE + HW_POWER_5VCTRL);
p5vctrl &= ~(HW_POWER_5VCTRL_PWRUP_VBUS_CMPS |
HW_POWER_5VCTRL_VBUSVALID_5VDETECT |
HW_POWER_5VCTRL_VBUSVALID_TRSH);
p5vctrl |= __SHIFTOUT(p5vctrl_saved, HW_POWER_5VCTRL_VBUSVALID_TRSH) |
(p5vctrl_saved & HW_POWER_5VCTRL_PWRUP_VBUS_CMPS) |
(p5vctrl_saved & HW_POWER_5VCTRL_VBUSVALID_5VDETECT);
REG_WRITE(HW_POWER_BASE + HW_POWER_5VCTRL, p5vctrl);
return;
}
void
enable_vddmem(void)
{
uint32_t vddctrl;
/* VDDMEM */
vddctrl = REG_READ(HW_POWER_BASE + HW_POWER_VDDMEMCTRL);
vddctrl |= (HW_POWER_VDDMEMCTRL_PULLDOWN_ACTIVE |
HW_POWER_VDDMEMCTRL_ENABLE_ILIMIT |
HW_POWER_VDDMEMCTRL_ENABLE_LINREG);
REG_WRITE(HW_POWER_BASE + HW_POWER_VDDMEMCTRL, vddctrl);
delay_us(500);
vddctrl &= ~(HW_POWER_VDDMEMCTRL_PULLDOWN_ACTIVE |
HW_POWER_VDDMEMCTRL_ENABLE_ILIMIT);
REG_WRITE(HW_POWER_BASE + HW_POWER_VDDMEMCTRL, vddctrl);
return;
}