commit
3e1b36bd58
@ -0,0 +1,162 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2013 - ARM Ltd |
||||||
|
* Author: Marc Zyngier <marc.zyngier@arm.com>
|
||||||
|
* |
||||||
|
* Based on code by Carl van Schaik <carl@ok-labs.com>.
|
||||||
|
* |
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as |
||||||
|
* published by the Free Software Foundation. |
||||||
|
* |
||||||
|
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>. |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <config.h> |
||||||
|
#include <asm/psci.h> |
||||||
|
#include <asm/arch/cpu.h> |
||||||
|
|
||||||
|
/* |
||||||
|
* Memory layout: |
||||||
|
* |
||||||
|
* SECURE_RAM to text_end : |
||||||
|
* ._secure_text section
|
||||||
|
* text_end to ALIGN_PAGE(text_end): |
||||||
|
* nothing |
||||||
|
* ALIGN_PAGE(text_end) to ALIGN_PAGE(text_end) + 0x1000) |
||||||
|
* 1kB of stack per CPU (4 CPUs max). |
||||||
|
*/ |
||||||
|
|
||||||
|
.pushsection ._secure.text, "ax" |
||||||
|
|
||||||
|
.arch_extension sec
|
||||||
|
|
||||||
|
#define ONE_MS (CONFIG_SYS_CLK_FREQ / 1000) |
||||||
|
#define TEN_MS (10 * ONE_MS) |
||||||
|
|
||||||
|
.macro timer_wait reg, ticks |
||||||
|
@ Program CNTP_TVAL
|
||||||
|
movw \reg, #(\ticks & 0xffff) |
||||||
|
movt \reg, #(\ticks >> 16) |
||||||
|
mcr p15, 0, \reg, c14, c2, 0 |
||||||
|
isb |
||||||
|
@ Enable physical timer, mask interrupt
|
||||||
|
mov \reg, #3 |
||||||
|
mcr p15, 0, \reg, c14, c2, 1 |
||||||
|
@ Poll physical timer until ISTATUS is on
|
||||||
|
1: isb |
||||||
|
mrc p15, 0, \reg, c14, c2, 1 |
||||||
|
ands \reg, \reg, #4 |
||||||
|
bne 1b |
||||||
|
@ Disable timer
|
||||||
|
mov \reg, #0 |
||||||
|
mcr p15, 0, \reg, c14, c2, 1 |
||||||
|
isb |
||||||
|
.endm |
||||||
|
|
||||||
|
.globl psci_arch_init
|
||||||
|
psci_arch_init: |
||||||
|
mrc p15, 0, r5, c1, c1, 0 @ Read SCR
|
||||||
|
bic r5, r5, #1 @ Secure mode
|
||||||
|
mcr p15, 0, r5, c1, c1, 0 @ Write SCR
|
||||||
|
isb |
||||||
|
|
||||||
|
mrc p15, 0, r4, c0, c0, 5 @ MPIDR
|
||||||
|
and r4, r4, #3 @ cpu number in cluster
|
||||||
|
mov r5, #400 @ 1kB of stack per CPU
|
||||||
|
mul r4, r4, r5 |
||||||
|
|
||||||
|
adr r5, text_end @ end of text
|
||||||
|
add r5, r5, #0x2000 @ Skip two pages
|
||||||
|
lsr r5, r5, #12 @ Align to start of page
|
||||||
|
lsl r5, r5, #12 |
||||||
|
sub sp, r5, r4 @ here's our stack!
|
||||||
|
|
||||||
|
bx lr |
||||||
|
|
||||||
|
@ r1 = target CPU
|
||||||
|
@ r2 = target PC
|
||||||
|
.globl psci_cpu_on
|
||||||
|
psci_cpu_on: |
||||||
|
adr r0, _target_pc |
||||||
|
str r2, [r0] |
||||||
|
dsb |
||||||
|
|
||||||
|
movw r0, #(SUNXI_CPUCFG_BASE & 0xffff) |
||||||
|
movt r0, #(SUNXI_CPUCFG_BASE >> 16) |
||||||
|
|
||||||
|
@ CPU mask
|
||||||
|
and r1, r1, #3 @ only care about first cluster
|
||||||
|
mov r4, #1 |
||||||
|
lsl r4, r4, r1 |
||||||
|
|
||||||
|
adr r6, _sunxi_cpu_entry |
||||||
|
str r6, [r0, #0x1a4] @ PRIVATE_REG (boot vector)
|
||||||
|
|
||||||
|
@ Assert reset on target CPU
|
||||||
|
mov r6, #0 |
||||||
|
lsl r5, r1, #6 @ 64 bytes per CPU
|
||||||
|
add r5, r5, #0x40 @ Offset from base
|
||||||
|
add r5, r5, r0 @ CPU control block
|
||||||
|
str r6, [r5] @ Reset CPU
|
||||||
|
|
||||||
|
@ l1 invalidate
|
||||||
|
ldr r6, [r0, #0x184] |
||||||
|
bic r6, r6, r4 |
||||||
|
str r6, [r0, #0x184] |
||||||
|
|
||||||
|
@ Lock CPU
|
||||||
|
ldr r6, [r0, #0x1e4] |
||||||
|
bic r6, r6, r4 |
||||||
|
str r6, [r0, #0x1e4] |
||||||
|
|
||||||
|
@ Release power clamp
|
||||||
|
movw r6, #0x1ff |
||||||
|
movt r6, #0 |
||||||
|
1: lsrs r6, r6, #1 |
||||||
|
str r6, [r0, #0x1b0] |
||||||
|
bne 1b |
||||||
|
|
||||||
|
timer_wait r1, TEN_MS |
||||||
|
|
||||||
|
@ Clear power gating
|
||||||
|
ldr r6, [r0, #0x1b4] |
||||||
|
bic r6, r6, #1 |
||||||
|
str r6, [r0, #0x1b4] |
||||||
|
|
||||||
|
@ Deassert reset on target CPU
|
||||||
|
mov r6, #3 |
||||||
|
str r6, [r5] |
||||||
|
|
||||||
|
@ Unlock CPU
|
||||||
|
ldr r6, [r0, #0x1e4] |
||||||
|
orr r6, r6, r4 |
||||||
|
str r6, [r0, #0x1e4] |
||||||
|
|
||||||
|
mov r0, #ARM_PSCI_RET_SUCCESS @ Return PSCI_RET_SUCCESS |
||||||
|
mov pc, lr |
||||||
|
|
||||||
|
_target_pc: |
||||||
|
.word 0
|
||||||
|
|
||||||
|
_sunxi_cpu_entry: |
||||||
|
@ Set SMP bit
|
||||||
|
mrc p15, 0, r0, c1, c0, 1 |
||||||
|
orr r0, r0, #0x40 |
||||||
|
mcr p15, 0, r0, c1, c0, 1 |
||||||
|
isb |
||||||
|
|
||||||
|
bl _nonsec_init |
||||||
|
bl psci_arch_init |
||||||
|
|
||||||
|
adr r0, _target_pc |
||||||
|
ldr r0, [r0] |
||||||
|
b _do_nonsec_entry |
||||||
|
|
||||||
|
text_end: |
||||||
|
.popsection |
@ -0,0 +1,84 @@ |
|||||||
|
#include <common.h> |
||||||
|
#include <ahci.h> |
||||||
|
#include <scsi.h> |
||||||
|
#include <errno.h> |
||||||
|
#include <asm/io.h> |
||||||
|
#include <asm/gpio.h> |
||||||
|
|
||||||
|
#define AHCI_PHYCS0R 0x00c0 |
||||||
|
#define AHCI_PHYCS1R 0x00c4 |
||||||
|
#define AHCI_PHYCS2R 0x00c8 |
||||||
|
#define AHCI_RWCR 0x00fc |
||||||
|
|
||||||
|
/* This magic PHY initialisation was taken from the Allwinner releases
|
||||||
|
* and Linux driver, but is completely undocumented. |
||||||
|
*/ |
||||||
|
static int sunxi_ahci_phy_init(u32 base) |
||||||
|
{ |
||||||
|
u8 *reg_base = (u8 *)base; |
||||||
|
u32 reg_val; |
||||||
|
int timeout; |
||||||
|
|
||||||
|
writel(0, reg_base + AHCI_RWCR); |
||||||
|
mdelay(5); |
||||||
|
|
||||||
|
setbits_le32(reg_base + AHCI_PHYCS1R, 0x1 << 19); |
||||||
|
clrsetbits_le32(reg_base + AHCI_PHYCS0R, |
||||||
|
(0x7 << 24), |
||||||
|
(0x5 << 24) | (0x1 << 23) | (0x1 << 18)); |
||||||
|
clrsetbits_le32(reg_base + AHCI_PHYCS1R, |
||||||
|
(0x3 << 16) | (0x1f << 8) | (0x3 << 6), |
||||||
|
(0x2 << 16) | (0x6 << 8) | (0x2 << 6)); |
||||||
|
setbits_le32(reg_base + AHCI_PHYCS1R, (0x1 << 28) | (0x1 << 15)); |
||||||
|
clrbits_le32(reg_base + AHCI_PHYCS1R, (0x1 << 19)); |
||||||
|
clrsetbits_le32(reg_base + AHCI_PHYCS0R, (0x7 << 20), (0x3 << 20)); |
||||||
|
clrsetbits_le32(reg_base + AHCI_PHYCS2R, (0x1f << 5), (0x19 << 5)); |
||||||
|
mdelay(5); |
||||||
|
|
||||||
|
setbits_le32(reg_base + AHCI_PHYCS0R, (0x1 << 19)); |
||||||
|
|
||||||
|
timeout = 250; /* Power up takes approx 50 us */ |
||||||
|
for (;;) { |
||||||
|
reg_val = readl(reg_base + AHCI_PHYCS0R) & (0x7 << 28); |
||||||
|
if (reg_val == (0x2 << 28)) |
||||||
|
break; |
||||||
|
if (--timeout == 0) { |
||||||
|
printf("AHCI PHY power up failed.\n"); |
||||||
|
return -EIO; |
||||||
|
} |
||||||
|
udelay(1); |
||||||
|
}; |
||||||
|
|
||||||
|
setbits_le32(reg_base + AHCI_PHYCS2R, (0x1 << 24)); |
||||||
|
|
||||||
|
timeout = 100; /* Calibration takes approx 10 us */ |
||||||
|
for (;;) { |
||||||
|
reg_val = readl(reg_base + AHCI_PHYCS2R) & (0x1 << 24); |
||||||
|
if (reg_val == 0x0) |
||||||
|
break; |
||||||
|
if (--timeout == 0) { |
||||||
|
printf("AHCI PHY calibration failed.\n"); |
||||||
|
return -EIO; |
||||||
|
} |
||||||
|
udelay(1); |
||||||
|
} |
||||||
|
|
||||||
|
mdelay(15); |
||||||
|
|
||||||
|
writel(0x7, reg_base + AHCI_RWCR); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
void scsi_init(void) |
||||||
|
{ |
||||||
|
printf("SUNXI SCSI INIT\n"); |
||||||
|
#ifdef CONFIG_SATAPWR |
||||||
|
gpio_direction_output(CONFIG_SATAPWR, 1); |
||||||
|
#endif |
||||||
|
|
||||||
|
if (sunxi_ahci_phy_init(SUNXI_SATA_BASE) < 0) |
||||||
|
return; |
||||||
|
|
||||||
|
ahci_init(SUNXI_SATA_BASE); |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
/* this file is generated, don't edit it yourself */ |
||||||
|
|
||||||
|
#include <common.h> |
||||||
|
#include <asm/arch/dram.h> |
||||||
|
|
||||||
|
static struct dram_para dram_para = { |
||||||
|
.clock = 480, |
||||||
|
.type = 3, |
||||||
|
.rank_num = 1, |
||||||
|
.density = 4096, |
||||||
|
.io_width = 16, |
||||||
|
.bus_width = 16, |
||||||
|
.cas = 6, |
||||||
|
.zq = 123, |
||||||
|
.odt_en = 0, |
||||||
|
.size = 512, |
||||||
|
.tpr0 = 0x30926692, |
||||||
|
.tpr1 = 0x1090, |
||||||
|
.tpr2 = 0x1a0c8, |
||||||
|
.tpr3 = 0, |
||||||
|
.tpr4 = 0, |
||||||
|
.tpr5 = 0, |
||||||
|
.emr1 = 0x4, |
||||||
|
.emr2 = 0, |
||||||
|
.emr3 = 0, |
||||||
|
}; |
||||||
|
|
||||||
|
unsigned long sunxi_dram_init(void) |
||||||
|
{ |
||||||
|
return dramc_init(&dram_para); |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
/* this file is generated, don't edit it yourself */ |
||||||
|
|
||||||
|
#include <common.h> |
||||||
|
#include <asm/arch/dram.h> |
||||||
|
|
||||||
|
static struct dram_para dram_para = { |
||||||
|
.clock = 432, |
||||||
|
.type = 3, |
||||||
|
.rank_num = 1, |
||||||
|
.density = 4096, |
||||||
|
.io_width = 16, |
||||||
|
.bus_width = 16, |
||||||
|
.cas = 9, |
||||||
|
.zq = 123, |
||||||
|
.odt_en = 0, |
||||||
|
.size = 512, |
||||||
|
.tpr0 = 0x42d899b7, |
||||||
|
.tpr1 = 0xa090, |
||||||
|
.tpr2 = 0x22a00, |
||||||
|
.tpr3 = 0, |
||||||
|
.tpr4 = 0, |
||||||
|
.tpr5 = 0, |
||||||
|
.emr1 = 0x4, |
||||||
|
.emr2 = 0x10, |
||||||
|
.emr3 = 0, |
||||||
|
}; |
||||||
|
|
||||||
|
unsigned long sunxi_dram_init(void) |
||||||
|
{ |
||||||
|
return dramc_init(&dram_para); |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
/* this file is generated, don't edit it yourself */ |
||||||
|
|
||||||
|
#include <common.h> |
||||||
|
#include <asm/arch/dram.h> |
||||||
|
|
||||||
|
static struct dram_para dram_para = { |
||||||
|
.clock = 408, |
||||||
|
.type = 3, |
||||||
|
.rank_num = 1, |
||||||
|
.density = 2048, |
||||||
|
.io_width = 8, |
||||||
|
.bus_width = 16, |
||||||
|
.cas = 9, |
||||||
|
.zq = 123, |
||||||
|
.odt_en = 0, |
||||||
|
.size = 512, |
||||||
|
.tpr0 = 0x42d899b7, |
||||||
|
.tpr1 = 0xa090, |
||||||
|
.tpr2 = 0x22a00, |
||||||
|
.tpr3 = 0, |
||||||
|
.tpr4 = 0, |
||||||
|
.tpr5 = 0, |
||||||
|
.emr1 = 0, |
||||||
|
.emr2 = 0x10, |
||||||
|
.emr3 = 0, |
||||||
|
}; |
||||||
|
|
||||||
|
unsigned long sunxi_dram_init(void) |
||||||
|
{ |
||||||
|
return dramc_init(&dram_para); |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
/* this file is generated, don't edit it yourself */ |
||||||
|
|
||||||
|
#include <common.h> |
||||||
|
#include <asm/arch/dram.h> |
||||||
|
|
||||||
|
static struct dram_para dram_para = { |
||||||
|
.clock = 432, |
||||||
|
.type = 3, |
||||||
|
.rank_num = 1, |
||||||
|
.density = 4096, |
||||||
|
.io_width = 16, |
||||||
|
.bus_width = 32, |
||||||
|
.cas = 9, |
||||||
|
.zq = 0x7f, |
||||||
|
.odt_en = 0, |
||||||
|
.size = 1024, |
||||||
|
.tpr0 = 0x42d899b7, |
||||||
|
.tpr1 = 0xa090, |
||||||
|
.tpr2 = 0x22a00, |
||||||
|
.tpr3 = 0x0, |
||||||
|
.tpr4 = 0x1, |
||||||
|
.tpr5 = 0x0, |
||||||
|
.emr1 = 0x4, |
||||||
|
.emr2 = 0x10, |
||||||
|
.emr3 = 0x0, |
||||||
|
}; |
||||||
|
|
||||||
|
unsigned long sunxi_dram_init(void) |
||||||
|
{ |
||||||
|
return dramc_init(&dram_para); |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
/* this file is generated, don't edit it yourself */ |
||||||
|
|
||||||
|
#include <common.h> |
||||||
|
#include <asm/arch/dram.h> |
||||||
|
|
||||||
|
static struct dram_para dram_para = { |
||||||
|
.clock = 480, |
||||||
|
.type = 3, |
||||||
|
.rank_num = 1, |
||||||
|
.density = 4096, |
||||||
|
.io_width = 16, |
||||||
|
.bus_width = 32, |
||||||
|
.cas = 9, |
||||||
|
.zq = 0x7a, |
||||||
|
.odt_en = 0, |
||||||
|
.size = 1024, |
||||||
|
.tpr0 = 0x42d899b7, |
||||||
|
.tpr1 = 0xa090, |
||||||
|
.tpr2 = 0x22a00, |
||||||
|
.tpr3 = 0, |
||||||
|
.tpr4 = 0, |
||||||
|
.tpr5 = 0, |
||||||
|
.emr1 = 0x4, |
||||||
|
.emr2 = 0x10, |
||||||
|
.emr3 = 0x0, |
||||||
|
}; |
||||||
|
|
||||||
|
unsigned long sunxi_dram_init(void) |
||||||
|
{ |
||||||
|
return dramc_init(&dram_para); |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
/* this file is generated, don't edit it yourself */ |
||||||
|
|
||||||
|
#include <common.h> |
||||||
|
#include <asm/arch/dram.h> |
||||||
|
|
||||||
|
static struct dram_para dram_para = { |
||||||
|
.clock = 360, |
||||||
|
.type = 3, |
||||||
|
.rank_num = 1, |
||||||
|
.density = 4096, |
||||||
|
.io_width = 16, |
||||||
|
.bus_width = 32, |
||||||
|
.cas = 6, |
||||||
|
.zq = 123, |
||||||
|
.odt_en = 0, |
||||||
|
.size = 1024, |
||||||
|
.tpr0 = 0x30926692, |
||||||
|
.tpr1 = 0x1090, |
||||||
|
.tpr2 = 0x1a0c8, |
||||||
|
.tpr3 = 0, |
||||||
|
.tpr4 = 0, |
||||||
|
.tpr5 = 0, |
||||||
|
.emr1 = 0, |
||||||
|
.emr2 = 0, |
||||||
|
.emr3 = 0, |
||||||
|
}; |
||||||
|
|
||||||
|
unsigned long sunxi_dram_init(void) |
||||||
|
{ |
||||||
|
return dramc_init(&dram_para); |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
/* this file is generated, don't edit it yourself */ |
||||||
|
|
||||||
|
#include <common.h> |
||||||
|
#include <asm/arch/dram.h> |
||||||
|
|
||||||
|
static struct dram_para dram_para = { |
||||||
|
.clock = 360, |
||||||
|
.type = 3, |
||||||
|
.rank_num = 1, |
||||||
|
.density = 2048, |
||||||
|
.io_width = 8, |
||||||
|
.bus_width = 32, |
||||||
|
.cas = 6, |
||||||
|
.zq = 123, |
||||||
|
.odt_en = 0, |
||||||
|
.size = 1024, |
||||||
|
.tpr0 = 0x30926692, |
||||||
|
.tpr1 = 0x1090, |
||||||
|
.tpr2 = 0x1a0c8, |
||||||
|
.tpr3 = 0, |
||||||
|
.tpr4 = 0, |
||||||
|
.tpr5 = 0, |
||||||
|
.emr1 = 0, |
||||||
|
.emr2 = 0, |
||||||
|
.emr3 = 0, |
||||||
|
}; |
||||||
|
|
||||||
|
unsigned long sunxi_dram_init(void) |
||||||
|
{ |
||||||
|
return dramc_init(&dram_para); |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
/* this file is generated, don't edit it yourself */ |
||||||
|
|
||||||
|
#include <common.h> |
||||||
|
#include <asm/arch/dram.h> |
||||||
|
|
||||||
|
static struct dram_para dram_para = { |
||||||
|
.clock = 360, |
||||||
|
.type = 3, |
||||||
|
.rank_num = 1, |
||||||
|
.density = 2048, |
||||||
|
.io_width = 16, |
||||||
|
.bus_width = 32, |
||||||
|
.cas = 6, |
||||||
|
.zq = 123, |
||||||
|
.odt_en = 0, |
||||||
|
.size = 512, |
||||||
|
.tpr0 = 0x30926692, |
||||||
|
.tpr1 = 0x1090, |
||||||
|
.tpr2 = 0x1a0c8, |
||||||
|
.tpr3 = 0, |
||||||
|
.tpr4 = 0, |
||||||
|
.tpr5 = 0, |
||||||
|
.emr1 = 0, |
||||||
|
.emr2 = 0, |
||||||
|
.emr3 = 0, |
||||||
|
}; |
||||||
|
|
||||||
|
unsigned long sunxi_dram_init(void) |
||||||
|
{ |
||||||
|
return dramc_init(&dram_para); |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
/* this file is generated, don't edit it yourself */ |
||||||
|
|
||||||
|
#include <common.h> |
||||||
|
#include <asm/arch/dram.h> |
||||||
|
|
||||||
|
static struct dram_para dram_para = { |
||||||
|
.clock = 384, |
||||||
|
.type = 3, |
||||||
|
.rank_num = 1, |
||||||
|
.density = 2048, |
||||||
|
.io_width = 8, |
||||||
|
.bus_width = 32, |
||||||
|
.cas = 6, |
||||||
|
.zq = 123, |
||||||
|
.odt_en = 0, |
||||||
|
.size = 1024, |
||||||
|
.tpr0 = 0x30926692, |
||||||
|
.tpr1 = 0x1090, |
||||||
|
.tpr2 = 0x1a0c8, |
||||||
|
.tpr3 = 0, |
||||||
|
.tpr4 = 0, |
||||||
|
.tpr5 = 0, |
||||||
|
.emr1 = 0x4, |
||||||
|
.emr2 = 0, |
||||||
|
.emr3 = 0, |
||||||
|
}; |
||||||
|
|
||||||
|
unsigned long sunxi_dram_init(void) |
||||||
|
{ |
||||||
|
return dramc_init(&dram_para); |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
/* this file is generated, don't edit it yourself */ |
||||||
|
|
||||||
|
#include "common.h" |
||||||
|
#include <asm/arch/dram.h> |
||||||
|
|
||||||
|
static struct dram_para dram_para = { |
||||||
|
.clock = 384, |
||||||
|
.type = 3, |
||||||
|
.rank_num = 1, |
||||||
|
.density = 4096, |
||||||
|
.io_width = 16, |
||||||
|
.bus_width = 32, |
||||||
|
.cas = 9, |
||||||
|
.zq = 0x7f, |
||||||
|
.odt_en = 0, |
||||||
|
.size = 1024, |
||||||
|
.tpr0 = 0x42d899b7, |
||||||
|
.tpr1 = 0xa090, |
||||||
|
.tpr2 = 0x22a00, |
||||||
|
.tpr3 = 0, |
||||||
|
.tpr4 = 0, |
||||||
|
.tpr5 = 0, |
||||||
|
.emr1 = 0x4, |
||||||
|
.emr2 = 0x10, |
||||||
|
.emr3 = 0, |
||||||
|
}; |
||||||
|
|
||||||
|
unsigned long sunxi_dram_init(void) |
||||||
|
{ |
||||||
|
return dramc_init(&dram_para); |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
/* this file is generated, don't edit it yourself */ |
||||||
|
|
||||||
|
#include "common.h" |
||||||
|
#include <asm/arch/dram.h> |
||||||
|
|
||||||
|
static struct dram_para dram_para = { |
||||||
|
.clock = 384, |
||||||
|
.type = 3, |
||||||
|
.rank_num = 1, |
||||||
|
.density = 4096, |
||||||
|
.io_width = 16, |
||||||
|
.bus_width = 16, |
||||||
|
.cas = 9, |
||||||
|
.zq = 0x7f, |
||||||
|
.odt_en = 0, |
||||||
|
.size = 512, |
||||||
|
.tpr0 = 0x42d899b7, |
||||||
|
.tpr1 = 0xa090, |
||||||
|
.tpr2 = 0x22a00, |
||||||
|
.tpr3 = 0, |
||||||
|
.tpr4 = 0, |
||||||
|
.tpr5 = 0, |
||||||
|
.emr1 = 0x4, |
||||||
|
.emr2 = 0x10, |
||||||
|
.emr3 = 0, |
||||||
|
}; |
||||||
|
|
||||||
|
unsigned long sunxi_dram_init(void) |
||||||
|
{ |
||||||
|
return dramc_init(&dram_para); |
||||||
|
} |
@ -0,0 +1,4 @@ |
|||||||
|
CONFIG_SPL=y |
||||||
|
CONFIG_SYS_EXTRA_OPTIONS="A10_OLINUXINO_L,SPL,AXP209_POWER,SUNXI_EMAC,AHCI,SATAPWR=SUNXI_GPC(3),USB_EHCI" |
||||||
|
+S:CONFIG_ARM=y |
||||||
|
+S:CONFIG_TARGET_SUN4I=y |
@ -0,0 +1,4 @@ |
|||||||
|
CONFIG_SPL=y |
||||||
|
CONFIG_SYS_EXTRA_OPTIONS="A10S_OLINUXINO_M,SPL,AXP152_POWER,SUNXI_EMAC,USB_EHCI,SUNXI_USB_VBUS0_GPIO=SUNXI_GPB(10)" |
||||||
|
+S:CONFIG_ARM=y |
||||||
|
+S:CONFIG_TARGET_SUN5I=y |
@ -1,4 +1,4 @@ |
|||||||
CONFIG_SPL=y |
CONFIG_SPL=y |
||||||
CONFIG_SYS_EXTRA_OPTIONS="A13_OLINUXINOM,SPL,CONS_INDEX=2" |
CONFIG_SYS_EXTRA_OPTIONS="A13_OLINUXINOM,SPL,CONS_INDEX=2,USB_EHCI,SUNXI_USB_VBUS0_GPIO=SUNXI_GPG(11)" |
||||||
+S:CONFIG_ARM=y |
+S:CONFIG_ARM=y |
||||||
+S:CONFIG_TARGET_SUN5I=y |
+S:CONFIG_TARGET_SUN5I=y |
||||||
|
@ -0,0 +1,4 @@ |
|||||||
|
CONFIG_SPL=y |
||||||
|
CONFIG_SYS_EXTRA_OPTIONS="A13_OLINUXINO,SPL,CONS_INDEX=2,AXP209_POWER,USB_EHCI,SUNXI_USB_VBUS0_GPIO=SUNXI_GPG(11)" |
||||||
|
+S:CONFIG_ARM=y |
||||||
|
+S:CONFIG_TARGET_SUN5I=y |
@ -0,0 +1,4 @@ |
|||||||
|
CONFIG_SPL=y |
||||||
|
CONFIG_SYS_EXTRA_OPTIONS="A20_OLINUXINO_M,SPL,AXP209_POWER,SUNXI_GMAC,AHCI,SATAPWR=SUNXI_GPB(8),USB_EHCI" |
||||||
|
+S:CONFIG_ARM=y |
||||||
|
+S:CONFIG_TARGET_SUN7I=y |
@ -0,0 +1,4 @@ |
|||||||
|
CONFIG_SPL=y |
||||||
|
CONFIG_SYS_EXTRA_OPTIONS="AUXTEK_T004,SPL,AXP152_POWER,USB_EHCI,SUNXI_USB_VBUS0_GPIO=SUNXI_GPG(13)" |
||||||
|
+S:CONFIG_ARM=y |
||||||
|
+S:CONFIG_TARGET_SUN5I=y |
@ -0,0 +1,4 @@ |
|||||||
|
CONFIG_SPL=y |
||||||
|
CONFIG_SYS_EXTRA_OPTIONS="BANANAPI,SPL,AXP209_POWER,SUNXI_GMAC,RGMII,MACPWR=SUNXI_GPH(23),AHCI,USB_EHCI" |
||||||
|
+S:CONFIG_ARM=y |
||||||
|
+S:CONFIG_TARGET_SUN7I=y |
@ -1,4 +1,4 @@ |
|||||||
CONFIG_SPL=y |
CONFIG_SPL=y |
||||||
CONFIG_SYS_EXTRA_OPTIONS="CUBIEBOARD2,SPL_FEL,SUNXI_GMAC" |
CONFIG_SYS_EXTRA_OPTIONS="CUBIEBOARD2,SPL_FEL,AXP209_POWER,SUNXI_GMAC,AHCI,SATAPWR=SUNXI_GPB(8),USB_EHCI" |
||||||
+S:CONFIG_ARM=y |
+S:CONFIG_ARM=y |
||||||
+S:CONFIG_TARGET_SUN7I=y |
+S:CONFIG_TARGET_SUN7I=y |
||||||
|
@ -1,4 +1,4 @@ |
|||||||
CONFIG_SPL=y |
CONFIG_SPL=y |
||||||
CONFIG_SYS_EXTRA_OPTIONS="CUBIEBOARD2,SPL,SUNXI_GMAC" |
CONFIG_SYS_EXTRA_OPTIONS="CUBIEBOARD2,SPL,AXP209_POWER,SUNXI_GMAC,AHCI,SATAPWR=SUNXI_GPB(8),USB_EHCI" |
||||||
+S:CONFIG_ARM=y |
+S:CONFIG_ARM=y |
||||||
+S:CONFIG_TARGET_SUN7I=y |
+S:CONFIG_TARGET_SUN7I=y |
||||||
|
@ -1,4 +1,4 @@ |
|||||||
CONFIG_SPL=y |
CONFIG_SPL=y |
||||||
CONFIG_SYS_EXTRA_OPTIONS="CUBIEBOARD,SPL,AXP209_POWER,SUNXI_EMAC" |
CONFIG_SYS_EXTRA_OPTIONS="CUBIEBOARD,SPL,AXP209_POWER,SUNXI_EMAC,AHCI,SATAPWR=SUNXI_GPB(8),USB_EHCI" |
||||||
+S:CONFIG_ARM=y |
+S:CONFIG_ARM=y |
||||||
+S:CONFIG_TARGET_SUN4I=y |
+S:CONFIG_TARGET_SUN4I=y |
||||||
|
@ -1,4 +1,4 @@ |
|||||||
CONFIG_SPL=y |
CONFIG_SPL=y |
||||||
CONFIG_SYS_EXTRA_OPTIONS="CUBIETRUCK,SPL_FEL,AXP209_POWER,SUNXI_GMAC,RGMII" |
CONFIG_SYS_EXTRA_OPTIONS="CUBIETRUCK,SPL_FEL,AXP209_POWER,SUNXI_GMAC,RGMII,AHCI,SATAPWR=SUNXI_GPH(12),USB_EHCI" |
||||||
+S:CONFIG_ARM=y |
+S:CONFIG_ARM=y |
||||||
+S:CONFIG_TARGET_SUN7I=y |
+S:CONFIG_TARGET_SUN7I=y |
||||||
|
@ -1,4 +1,4 @@ |
|||||||
CONFIG_SPL=y |
CONFIG_SPL=y |
||||||
CONFIG_SYS_EXTRA_OPTIONS="CUBIETRUCK,SPL,AXP209_POWER,SUNXI_GMAC,RGMII" |
CONFIG_SYS_EXTRA_OPTIONS="CUBIETRUCK,SPL,AXP209_POWER,SUNXI_GMAC,RGMII,AHCI,SATAPWR=SUNXI_GPH(12),USB_EHCI" |
||||||
+S:CONFIG_ARM=y |
+S:CONFIG_ARM=y |
||||||
+S:CONFIG_TARGET_SUN7I=y |
+S:CONFIG_TARGET_SUN7I=y |
||||||
|
@ -0,0 +1,4 @@ |
|||||||
|
CONFIG_SPL=y |
||||||
|
CONFIG_SYS_EXTRA_OPTIONS="PCDUINO3,SPL,AXP209_POWER,SUNXI_GMAC,AHCI,SATAPWR=SUNXI_GPH(2),USB_EHCI" |
||||||
|
+S:CONFIG_ARM=y |
||||||
|
+S:CONFIG_TARGET_SUN7I=y |
@ -0,0 +1,4 @@ |
|||||||
|
CONFIG_SPL=y |
||||||
|
CONFIG_SYS_EXTRA_OPTIONS="MELE_A1000G,SPL,AXP209_POWER,SUNXI_EMAC,MACPWR=SUNXI_GPH(15),AHCI,USB_EHCI" |
||||||
|
+S:CONFIG_ARM=y |
||||||
|
+S:CONFIG_TARGET_SUN4I=y |
@ -0,0 +1,4 @@ |
|||||||
|
CONFIG_SPL=y |
||||||
|
CONFIG_SYS_EXTRA_OPTIONS="MELE_A1000,SPL,AXP209_POWER,SUNXI_EMAC,MACPWR=SUNXI_GPH(15),AHCI,USB_EHCI" |
||||||
|
+S:CONFIG_ARM=y |
||||||
|
+S:CONFIG_TARGET_SUN4I=y |
@ -0,0 +1,4 @@ |
|||||||
|
CONFIG_SPL=y |
||||||
|
CONFIG_SYS_EXTRA_OPTIONS="MINI_X_1GB,SPL,AXP209_POWER,USB_EHCI" |
||||||
|
+S:CONFIG_ARM=y |
||||||
|
+S:CONFIG_TARGET_SUN4I=y |
@ -0,0 +1,4 @@ |
|||||||
|
CONFIG_SPL=y |
||||||
|
CONFIG_SYS_EXTRA_OPTIONS="MINI_X,SPL,AXP209_POWER,USB_EHCI" |
||||||
|
+S:CONFIG_ARM=y |
||||||
|
+S:CONFIG_TARGET_SUN4I=y |
@ -0,0 +1,4 @@ |
|||||||
|
CONFIG_SPL=y |
||||||
|
CONFIG_SYS_EXTRA_OPTIONS="BA10_TV_BOX,SPL,AXP209_POWER,SUNXI_EMAC,USB_EHCI,SUNXI_USB_VBUS1_GPIO=SUNXI_GPH(12)" |
||||||
|
+S:CONFIG_ARM=y |
||||||
|
+S:CONFIG_TARGET_SUN4I=y |
@ -0,0 +1,4 @@ |
|||||||
|
CONFIG_SPL=y |
||||||
|
CONFIG_SYS_EXTRA_OPTIONS="I12_TVBOX,SPL,AXP209_POWER,SUNXI_GMAC,MACPWR=SUNXI_GPH(21),USB_EHCI" |
||||||
|
+S:CONFIG_ARM=y |
||||||
|
+S:CONFIG_TARGET_SUN7I=y |
@ -0,0 +1,4 @@ |
|||||||
|
CONFIG_SPL=y |
||||||
|
CONFIG_SYS_EXTRA_OPTIONS="QT840A,SPL,AXP209_POWER,SUNXI_GMAC,MACPWR=SUNXI_GPH(21),USB_EHCI" |
||||||
|
+S:CONFIG_ARM=y |
||||||
|
+S:CONFIG_TARGET_SUN7I=y |
@ -1,4 +1,4 @@ |
|||||||
CONFIG_SPL=y |
CONFIG_SPL=y |
||||||
CONFIG_SYS_EXTRA_OPTIONS="R7DONGLE,SPL,AXP152_POWER" |
CONFIG_SYS_EXTRA_OPTIONS="R7DONGLE,SPL,AXP152_POWER,USB_EHCI,SUNXI_USB_VBUS0_GPIO=SUNXI_GPG(13)" |
||||||
+S:CONFIG_ARM=y |
+S:CONFIG_ARM=y |
||||||
+S:CONFIG_TARGET_SUN5I=y |
+S:CONFIG_TARGET_SUN5I=y |
||||||
|
@ -0,0 +1,201 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Roman Byshko |
||||||
|
* |
||||||
|
* Roman Byshko <rbyshko@gmail.com> |
||||||
|
* |
||||||
|
* Based on code from |
||||||
|
* Allwinner Technology Co., Ltd. <www.allwinnertech.com> |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: GPL-2.0+ |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <asm/arch/clock.h> |
||||||
|
#include <asm/gpio.h> |
||||||
|
#include <asm/io.h> |
||||||
|
#include <common.h> |
||||||
|
#include "ehci.h" |
||||||
|
|
||||||
|
#define SUNXI_USB1_IO_BASE 0x01c14000 |
||||||
|
#define SUNXI_USB2_IO_BASE 0x01c1c000 |
||||||
|
|
||||||
|
#define SUNXI_USB_PMU_IRQ_ENABLE 0x800 |
||||||
|
#define SUNXI_USB_CSR 0x01c13404 |
||||||
|
#define SUNXI_USB_PASSBY_EN 1 |
||||||
|
|
||||||
|
#define SUNXI_EHCI_AHB_ICHR8_EN (1 << 10) |
||||||
|
#define SUNXI_EHCI_AHB_INCR4_BURST_EN (1 << 9) |
||||||
|
#define SUNXI_EHCI_AHB_INCRX_ALIGN_EN (1 << 8) |
||||||
|
#define SUNXI_EHCI_ULPI_BYPASS_EN (1 << 0) |
||||||
|
|
||||||
|
static struct sunxi_ehci_hcd { |
||||||
|
struct usb_hcd *hcd; |
||||||
|
int usb_rst_mask; |
||||||
|
int ahb_clk_mask; |
||||||
|
int gpio_vbus; |
||||||
|
void *csr; |
||||||
|
int irq; |
||||||
|
int id; |
||||||
|
} sunxi_echi_hcd[] = { |
||||||
|
{ |
||||||
|
.usb_rst_mask = CCM_USB_CTRL_PHY1_RST, |
||||||
|
.ahb_clk_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0, |
||||||
|
.gpio_vbus = CONFIG_SUNXI_USB_VBUS0_GPIO, |
||||||
|
.csr = (void *)SUNXI_USB_CSR, |
||||||
|
.irq = 39, |
||||||
|
.id = 1, |
||||||
|
}, |
||||||
|
#if (CONFIG_USB_MAX_CONTROLLER_COUNT > 1) |
||||||
|
{ |
||||||
|
.usb_rst_mask = CCM_USB_CTRL_PHY2_RST, |
||||||
|
.ahb_clk_mask = 1 << AHB_GATE_OFFSET_USB_EHCI1, |
||||||
|
.gpio_vbus = CONFIG_SUNXI_USB_VBUS1_GPIO, |
||||||
|
.csr = (void *)SUNXI_USB_CSR, |
||||||
|
.irq = 40, |
||||||
|
.id = 2, |
||||||
|
} |
||||||
|
#endif |
||||||
|
}; |
||||||
|
|
||||||
|
static int enabled_hcd_count; |
||||||
|
|
||||||
|
static void *get_io_base(int hcd_id) |
||||||
|
{ |
||||||
|
if (hcd_id == 1) |
||||||
|
return (void *)SUNXI_USB1_IO_BASE; |
||||||
|
else if (hcd_id == 2) |
||||||
|
return (void *)SUNXI_USB2_IO_BASE; |
||||||
|
else |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
static void usb_phy_write(struct sunxi_ehci_hcd *sunxi_ehci, int addr, |
||||||
|
int data, int len) |
||||||
|
{ |
||||||
|
int j = 0, usbc_bit = 0; |
||||||
|
void *dest = sunxi_ehci->csr; |
||||||
|
|
||||||
|
usbc_bit = 1 << (sunxi_ehci->id * 2); |
||||||
|
for (j = 0; j < len; j++) { |
||||||
|
/* set the bit address to be written */ |
||||||
|
clrbits_le32(dest, 0xff << 8); |
||||||
|
setbits_le32(dest, (addr + j) << 8); |
||||||
|
|
||||||
|
clrbits_le32(dest, usbc_bit); |
||||||
|
/* set data bit */ |
||||||
|
if (data & 0x1) |
||||||
|
setbits_le32(dest, 1 << 7); |
||||||
|
else |
||||||
|
clrbits_le32(dest, 1 << 7); |
||||||
|
|
||||||
|
setbits_le32(dest, usbc_bit); |
||||||
|
|
||||||
|
clrbits_le32(dest, usbc_bit); |
||||||
|
|
||||||
|
data >>= 1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void sunxi_usb_phy_init(struct sunxi_ehci_hcd *sunxi_ehci) |
||||||
|
{ |
||||||
|
/* The following comments are machine
|
||||||
|
* translated from Chinese, you have been warned! |
||||||
|
*/ |
||||||
|
|
||||||
|
/* adjust PHY's magnitude and rate */ |
||||||
|
usb_phy_write(sunxi_ehci, 0x20, 0x14, 5); |
||||||
|
|
||||||
|
/* threshold adjustment disconnect */ |
||||||
|
#ifdef CONFIG_SUN4I |
||||||
|
usb_phy_write(sunxi_ehci, 0x2a, 3, 2); |
||||||
|
#else |
||||||
|
usb_phy_write(sunxi_ehci, 0x2a, 2, 2); |
||||||
|
#endif |
||||||
|
|
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
static void sunxi_usb_passby(struct sunxi_ehci_hcd *sunxi_ehci, int enable) |
||||||
|
{ |
||||||
|
unsigned long bits = 0; |
||||||
|
void *addr = get_io_base(sunxi_ehci->id) + SUNXI_USB_PMU_IRQ_ENABLE; |
||||||
|
|
||||||
|
bits = SUNXI_EHCI_AHB_ICHR8_EN | |
||||||
|
SUNXI_EHCI_AHB_INCR4_BURST_EN | |
||||||
|
SUNXI_EHCI_AHB_INCRX_ALIGN_EN | |
||||||
|
SUNXI_EHCI_ULPI_BYPASS_EN; |
||||||
|
|
||||||
|
if (enable) |
||||||
|
setbits_le32(addr, bits); |
||||||
|
else |
||||||
|
clrbits_le32(addr, bits); |
||||||
|
|
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
static void sunxi_ehci_enable(struct sunxi_ehci_hcd *sunxi_ehci) |
||||||
|
{ |
||||||
|
struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; |
||||||
|
|
||||||
|
setbits_le32(&ccm->usb_clk_cfg, sunxi_ehci->usb_rst_mask); |
||||||
|
setbits_le32(&ccm->ahb_gate0, sunxi_ehci->ahb_clk_mask); |
||||||
|
|
||||||
|
sunxi_usb_phy_init(sunxi_ehci); |
||||||
|
|
||||||
|
sunxi_usb_passby(sunxi_ehci, SUNXI_USB_PASSBY_EN); |
||||||
|
|
||||||
|
gpio_direction_output(sunxi_ehci->gpio_vbus, 1); |
||||||
|
} |
||||||
|
|
||||||
|
static void sunxi_ehci_disable(struct sunxi_ehci_hcd *sunxi_ehci) |
||||||
|
{ |
||||||
|
struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; |
||||||
|
|
||||||
|
gpio_direction_output(sunxi_ehci->gpio_vbus, 0); |
||||||
|
|
||||||
|
sunxi_usb_passby(sunxi_ehci, !SUNXI_USB_PASSBY_EN); |
||||||
|
|
||||||
|
clrbits_le32(&ccm->ahb_gate0, sunxi_ehci->ahb_clk_mask); |
||||||
|
clrbits_le32(&ccm->usb_clk_cfg, sunxi_ehci->usb_rst_mask); |
||||||
|
} |
||||||
|
|
||||||
|
int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, |
||||||
|
struct ehci_hcor **hcor) |
||||||
|
{ |
||||||
|
struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; |
||||||
|
struct sunxi_ehci_hcd *sunxi_ehci = &sunxi_echi_hcd[index]; |
||||||
|
|
||||||
|
/* enable common PHY only once */ |
||||||
|
if (index == 0) |
||||||
|
setbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE); |
||||||
|
|
||||||
|
sunxi_ehci_enable(sunxi_ehci); |
||||||
|
|
||||||
|
*hccr = get_io_base(sunxi_ehci->id); |
||||||
|
|
||||||
|
*hcor = (struct ehci_hcor *)((uint32_t) *hccr |
||||||
|
+ HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); |
||||||
|
|
||||||
|
debug("sunxi-ehci: init hccr %x and hcor %x hc_length %d\n", |
||||||
|
(uint32_t)*hccr, (uint32_t)*hcor, |
||||||
|
(uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); |
||||||
|
|
||||||
|
enabled_hcd_count++; |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
int ehci_hcd_stop(int index) |
||||||
|
{ |
||||||
|
struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; |
||||||
|
struct sunxi_ehci_hcd *sunxi_ehci = &sunxi_echi_hcd[index]; |
||||||
|
|
||||||
|
sunxi_ehci_disable(sunxi_ehci); |
||||||
|
|
||||||
|
/* disable common PHY only once, for the last enabled hcd */ |
||||||
|
if (enabled_hcd_count == 1) |
||||||
|
clrbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE); |
||||||
|
|
||||||
|
enabled_hcd_count--; |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
Loading…
Reference in new issue