Conflicts: drivers/spi/tegra20_sflash.c include/fdtdec.h lib/fdtdec.cmaster
commit
009d75ccc1
@ -0,0 +1,164 @@ |
||||
/*
|
||||
* (C) Copyright 2012 Stephen Warren |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as |
||||
* published by the Free Software Foundation; either version 2 of |
||||
* the License, or (at your option) any later version. |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <asm/io.h> |
||||
#include <asm/arch/mbox.h> |
||||
|
||||
#define TIMEOUT (100 * 1000) /* 100mS in uS */ |
||||
|
||||
int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv) |
||||
{ |
||||
struct bcm2835_mbox_regs *regs = |
||||
(struct bcm2835_mbox_regs *)BCM2835_MBOX_PHYSADDR; |
||||
ulong endtime = get_timer(0) + TIMEOUT; |
||||
u32 val; |
||||
|
||||
debug("time: %lu timeout: %lu\n", get_timer(0), endtime); |
||||
|
||||
if (send & BCM2835_CHAN_MASK) { |
||||
printf("mbox: Illegal mbox data 0x%08x\n", send); |
||||
return -1; |
||||
} |
||||
|
||||
/* Drain any stale responses */ |
||||
|
||||
for (;;) { |
||||
val = readl(®s->status); |
||||
if (val & BCM2835_MBOX_STATUS_RD_EMPTY) |
||||
break; |
||||
if (get_timer(0) >= endtime) { |
||||
printf("mbox: Timeout draining stale responses\n"); |
||||
return -1; |
||||
} |
||||
val = readl(®s->read); |
||||
} |
||||
|
||||
/* Wait for space to send */ |
||||
|
||||
for (;;) { |
||||
val = readl(®s->status); |
||||
if (!(val & BCM2835_MBOX_STATUS_WR_FULL)) |
||||
break; |
||||
if (get_timer(0) >= endtime) { |
||||
printf("mbox: Timeout waiting for send space\n"); |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
/* Send the request */ |
||||
|
||||
val = BCM2835_MBOX_PACK(chan, send); |
||||
debug("mbox: TX raw: 0x%08x\n", val); |
||||
writel(val, ®s->write); |
||||
|
||||
/* Wait for the response */ |
||||
|
||||
for (;;) { |
||||
val = readl(®s->status); |
||||
if (!(val & BCM2835_MBOX_STATUS_RD_EMPTY)) |
||||
break; |
||||
if (get_timer(0) >= endtime) { |
||||
printf("mbox: Timeout waiting for response\n"); |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
/* Read the response */ |
||||
|
||||
val = readl(®s->read); |
||||
debug("mbox: RX raw: 0x%08x\n", val); |
||||
|
||||
/* Validate the response */ |
||||
|
||||
if (BCM2835_MBOX_UNPACK_CHAN(val) != chan) { |
||||
printf("mbox: Response channel mismatch\n"); |
||||
return -1; |
||||
} |
||||
|
||||
*recv = BCM2835_MBOX_UNPACK_DATA(val); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
#ifdef DEBUG |
||||
void dump_buf(struct bcm2835_mbox_hdr *buffer) |
||||
{ |
||||
u32 *p; |
||||
u32 words; |
||||
int i; |
||||
|
||||
p = (u32 *)buffer; |
||||
words = buffer->buf_size / 4; |
||||
for (i = 0; i < words; i++) |
||||
printf(" 0x%04x: 0x%08x\n", i * 4, p[i]); |
||||
} |
||||
#endif |
||||
|
||||
int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_hdr *buffer) |
||||
{ |
||||
int ret; |
||||
u32 rbuffer; |
||||
struct bcm2835_mbox_tag_hdr *tag; |
||||
int tag_index; |
||||
|
||||
#ifdef DEBUG |
||||
printf("mbox: TX buffer\n"); |
||||
dump_buf(buffer); |
||||
#endif |
||||
|
||||
ret = bcm2835_mbox_call_raw(chan, (u32)buffer, &rbuffer); |
||||
if (ret) |
||||
return ret; |
||||
if (rbuffer != (u32)buffer) { |
||||
printf("mbox: Response buffer mismatch\n"); |
||||
return -1; |
||||
} |
||||
|
||||
#ifdef DEBUG |
||||
printf("mbox: RX buffer\n"); |
||||
dump_buf(buffer); |
||||
#endif |
||||
|
||||
/* Validate overall response status */ |
||||
|
||||
if (buffer->code != BCM2835_MBOX_RESP_CODE_SUCCESS) { |
||||
printf("mbox: Header response code invalid\n"); |
||||
return -1; |
||||
} |
||||
|
||||
/* Validate each tag's response status */ |
||||
|
||||
tag = (void *)(buffer + 1); |
||||
tag_index = 0; |
||||
while (tag->tag) { |
||||
if (!(tag->val_len & BCM2835_MBOX_TAG_VAL_LEN_RESPONSE)) { |
||||
printf("mbox: Tag %d missing val_len response bit\n", |
||||
tag_index); |
||||
return -1; |
||||
} |
||||
/*
|
||||
* Clear the reponse bit so clients can just look right at the |
||||
* length field without extra processing |
||||
*/ |
||||
tag->val_len &= ~BCM2835_MBOX_TAG_VAL_LEN_RESPONSE; |
||||
tag = (void *)(((u8 *)tag) + sizeof(*tag) + tag->val_buf_size); |
||||
tag_index++; |
||||
} |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,406 @@ |
||||
/*
|
||||
* clock_ti814x.c |
||||
* |
||||
* Clocks for TI814X based boards |
||||
* |
||||
* Copyright (C) 2013, Texas Instruments, Incorporated |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as |
||||
* published by the Free Software Foundation; either version 2 of |
||||
* the License, or (at your option) any later version. |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <asm/arch/cpu.h> |
||||
#include <asm/arch/clock.h> |
||||
#include <asm/arch/hardware.h> |
||||
#include <asm/io.h> |
||||
|
||||
/* PRCM */ |
||||
#define PRCM_MOD_EN 0x2 |
||||
|
||||
/* CLK_SRC */ |
||||
#define OSC_SRC0 0 |
||||
#define OSC_SRC1 1 |
||||
|
||||
#define L3_OSC_SRC OSC_SRC0 |
||||
|
||||
#define OSC_0_FREQ 20 |
||||
|
||||
#define DCO_HS2_MIN 500 |
||||
#define DCO_HS2_MAX 1000 |
||||
#define DCO_HS1_MIN 1000 |
||||
#define DCO_HS1_MAX 2000 |
||||
|
||||
#define SELFREQDCO_HS2 0x00000801 |
||||
#define SELFREQDCO_HS1 0x00001001 |
||||
|
||||
#define MPU_N 0x1 |
||||
#define MPU_M 0x3C |
||||
#define MPU_M2 1 |
||||
#define MPU_CLKCTRL 0x1 |
||||
|
||||
#define L3_N 19 |
||||
#define L3_M 880 |
||||
#define L3_M2 4 |
||||
#define L3_CLKCTRL 0x801 |
||||
|
||||
#define DDR_N 19 |
||||
#define DDR_M 666 |
||||
#define DDR_M2 2 |
||||
#define DDR_CLKCTRL 0x801 |
||||
|
||||
/* ADPLLJ register values */ |
||||
#define ADPLLJ_CLKCTRL_HS2 0x00000801 /* HS2 mode, TINT2 = 1 */ |
||||
#define ADPLLJ_CLKCTRL_HS1 0x00001001 /* HS1 mode, TINT2 = 1 */ |
||||
#define ADPLLJ_CLKCTRL_CLKDCOLDOEN (1 << 29) |
||||
#define ADPLLJ_CLKCTRL_IDLE (1 << 23) |
||||
#define ADPLLJ_CLKCTRL_CLKOUTEN (1 << 20) |
||||
#define ADPLLJ_CLKCTRL_CLKOUTLDOEN (1 << 19) |
||||
#define ADPLLJ_CLKCTRL_CLKDCOLDOPWDNZ (1 << 17) |
||||
#define ADPLLJ_CLKCTRL_LPMODE (1 << 12) |
||||
#define ADPLLJ_CLKCTRL_DRIFTGUARDIAN (1 << 11) |
||||
#define ADPLLJ_CLKCTRL_REGM4XEN (1 << 10) |
||||
#define ADPLLJ_CLKCTRL_TINITZ (1 << 0) |
||||
#define ADPLLJ_CLKCTRL_CLKDCO (ADPLLJ_CLKCTRL_CLKDCOLDOEN | \ |
||||
ADPLLJ_CLKCTRL_CLKOUTEN | \
|
||||
ADPLLJ_CLKCTRL_CLKOUTLDOEN | \
|
||||
ADPLLJ_CLKCTRL_CLKDCOLDOPWDNZ) |
||||
|
||||
#define ADPLLJ_STATUS_PHASELOCK (1 << 10) |
||||
#define ADPLLJ_STATUS_FREQLOCK (1 << 9) |
||||
#define ADPLLJ_STATUS_PHSFRQLOCK (ADPLLJ_STATUS_PHASELOCK | \ |
||||
ADPLLJ_STATUS_FREQLOCK) |
||||
#define ADPLLJ_STATUS_BYPASSACK (1 << 8) |
||||
#define ADPLLJ_STATUS_BYPASS (1 << 0) |
||||
#define ADPLLJ_STATUS_BYPASSANDACK (ADPLLJ_STATUS_BYPASSACK | \ |
||||
ADPLLJ_STATUS_BYPASS) |
||||
|
||||
#define ADPLLJ_TENABLE_ENB (1 << 0) |
||||
#define ADPLLJ_TENABLEDIV_ENB (1 << 0) |
||||
|
||||
#define ADPLLJ_M2NDIV_M2SHIFT 16 |
||||
|
||||
#define MPU_PLL_BASE (PLL_SUBSYS_BASE + 0x048) |
||||
#define L3_PLL_BASE (PLL_SUBSYS_BASE + 0x110) |
||||
#define DDR_PLL_BASE (PLL_SUBSYS_BASE + 0x290) |
||||
|
||||
struct ad_pll { |
||||
unsigned int pwrctrl; |
||||
unsigned int clkctrl; |
||||
unsigned int tenable; |
||||
unsigned int tenablediv; |
||||
unsigned int m2ndiv; |
||||
unsigned int mn2div; |
||||
unsigned int fracdiv; |
||||
unsigned int bwctrl; |
||||
unsigned int fracctrl; |
||||
unsigned int status; |
||||
unsigned int m3div; |
||||
unsigned int rampctrl; |
||||
}; |
||||
|
||||
#define OSC_SRC_CTRL (PLL_SUBSYS_BASE + 0x2C0) |
||||
|
||||
/* PRCM */ |
||||
#define CM_DEFAULT_BASE (PRCM_BASE + 0x0500) |
||||
|
||||
struct cm_def { |
||||
unsigned int resv0[2]; |
||||
unsigned int l3fastclkstctrl; |
||||
unsigned int resv1[1]; |
||||
unsigned int pciclkstctrl; |
||||
unsigned int resv2[1]; |
||||
unsigned int ducaticlkstctrl; |
||||
unsigned int resv3[1]; |
||||
unsigned int emif0clkctrl; |
||||
unsigned int emif1clkctrl; |
||||
unsigned int dmmclkctrl; |
||||
unsigned int fwclkctrl; |
||||
unsigned int resv4[10]; |
||||
unsigned int usbclkctrl; |
||||
unsigned int resv5[1]; |
||||
unsigned int sataclkctrl; |
||||
unsigned int resv6[4]; |
||||
unsigned int ducaticlkctrl; |
||||
unsigned int pciclkctrl; |
||||
}; |
||||
|
||||
#define CM_ALWON_BASE (PRCM_BASE + 0x1400) |
||||
|
||||
struct cm_alwon { |
||||
unsigned int l3slowclkstctrl; |
||||
unsigned int ethclkstctrl; |
||||
unsigned int l3medclkstctrl; |
||||
unsigned int mmu_clkstctrl; |
||||
unsigned int mmucfg_clkstctrl; |
||||
unsigned int ocmc0clkstctrl; |
||||
unsigned int vcpclkstctrl; |
||||
unsigned int mpuclkstctrl; |
||||
unsigned int sysclk4clkstctrl; |
||||
unsigned int sysclk5clkstctrl; |
||||
unsigned int sysclk6clkstctrl; |
||||
unsigned int rtcclkstctrl; |
||||
unsigned int l3fastclkstctrl; |
||||
unsigned int resv0[67]; |
||||
unsigned int mcasp0clkctrl; |
||||
unsigned int mcasp1clkctrl; |
||||
unsigned int mcasp2clkctrl; |
||||
unsigned int mcbspclkctrl; |
||||
unsigned int uart0clkctrl; |
||||
unsigned int uart1clkctrl; |
||||
unsigned int uart2clkctrl; |
||||
unsigned int gpio0clkctrl; |
||||
unsigned int gpio1clkctrl; |
||||
unsigned int i2c0clkctrl; |
||||
unsigned int i2c1clkctrl; |
||||
unsigned int mcasp345clkctrl; |
||||
unsigned int atlclkctrl; |
||||
unsigned int mlbclkctrl; |
||||
unsigned int pataclkctrl; |
||||
unsigned int resv1[1]; |
||||
unsigned int uart3clkctrl; |
||||
unsigned int uart4clkctrl; |
||||
unsigned int uart5clkctrl; |
||||
unsigned int wdtimerclkctrl; |
||||
unsigned int spiclkctrl; |
||||
unsigned int mailboxclkctrl; |
||||
unsigned int spinboxclkctrl; |
||||
unsigned int mmudataclkctrl; |
||||
unsigned int resv2[2]; |
||||
unsigned int mmucfgclkctrl; |
||||
unsigned int resv3[2]; |
||||
unsigned int ocmc0clkctrl; |
||||
unsigned int vcpclkctrl; |
||||
unsigned int resv4[2]; |
||||
unsigned int controlclkctrl; |
||||
unsigned int resv5[2]; |
||||
unsigned int gpmcclkctrl; |
||||
unsigned int ethernet0clkctrl; |
||||
unsigned int resv6[1]; |
||||
unsigned int mpuclkctrl; |
||||
unsigned int debugssclkctrl; |
||||
unsigned int l3clkctrl; |
||||
unsigned int l4hsclkctrl; |
||||
unsigned int l4lsclkctrl; |
||||
unsigned int rtcclkctrl; |
||||
unsigned int tpccclkctrl; |
||||
unsigned int tptc0clkctrl; |
||||
unsigned int tptc1clkctrl; |
||||
unsigned int tptc2clkctrl; |
||||
unsigned int tptc3clkctrl; |
||||
unsigned int resv7[4]; |
||||
unsigned int dcan01clkctrl; |
||||
unsigned int mmchs0clkctrl; |
||||
unsigned int mmchs1clkctrl; |
||||
unsigned int mmchs2clkctrl; |
||||
unsigned int custefuseclkctrl; |
||||
}; |
||||
|
||||
|
||||
const struct cm_alwon *cmalwon = (struct cm_alwon *)CM_ALWON_BASE; |
||||
const struct cm_def *cmdef = (struct cm_def *)CM_DEFAULT_BASE; |
||||
|
||||
/*
|
||||
* Enable the peripheral clock for required peripherals |
||||
*/ |
||||
static void enable_per_clocks(void) |
||||
{ |
||||
/* UART0 */ |
||||
writel(PRCM_MOD_EN, &cmalwon->uart0clkctrl); |
||||
while (readl(&cmalwon->uart0clkctrl) != PRCM_MOD_EN) |
||||
; |
||||
|
||||
/* HSMMC1 */ |
||||
writel(PRCM_MOD_EN, &cmalwon->mmchs1clkctrl); |
||||
while (readl(&cmalwon->mmchs1clkctrl) != PRCM_MOD_EN) |
||||
; |
||||
} |
||||
|
||||
/*
|
||||
* select the HS1 or HS2 for DCO Freq |
||||
* return : CLKCTRL |
||||
*/ |
||||
static u32 pll_dco_freq_sel(u32 clkout_dco) |
||||
{ |
||||
if (clkout_dco >= DCO_HS2_MIN && clkout_dco < DCO_HS2_MAX) |
||||
return SELFREQDCO_HS2; |
||||
else if (clkout_dco >= DCO_HS1_MIN && clkout_dco < DCO_HS1_MAX) |
||||
return SELFREQDCO_HS1; |
||||
else |
||||
return -1; |
||||
} |
||||
|
||||
/*
|
||||
* select the sigma delta config |
||||
* return: sigma delta val |
||||
*/ |
||||
static u32 pll_sigma_delta_val(u32 clkout_dco) |
||||
{ |
||||
u32 sig_val = 0; |
||||
float frac_div; |
||||
|
||||
frac_div = (float) clkout_dco / 250; |
||||
frac_div = frac_div + 0.90; |
||||
sig_val = (int)frac_div; |
||||
sig_val = sig_val << 24; |
||||
|
||||
return sig_val; |
||||
} |
||||
|
||||
/*
|
||||
* configure individual ADPLLJ |
||||
*/ |
||||
static void pll_config(u32 base, u32 n, u32 m, u32 m2, |
||||
u32 clkctrl_val, int adpllj) |
||||
{ |
||||
const struct ad_pll *adpll = (struct ad_pll *)base; |
||||
u32 m2nval, mn2val, read_clkctrl = 0, clkout_dco = 0; |
||||
u32 sig_val = 0, hs_mod = 0; |
||||
|
||||
m2nval = (m2 << ADPLLJ_M2NDIV_M2SHIFT) | n; |
||||
mn2val = m; |
||||
|
||||
/* calculate clkout_dco */ |
||||
clkout_dco = ((OSC_0_FREQ / (n+1)) * m); |
||||
|
||||
/* sigma delta & Hs mode selection skip for ADPLLS*/ |
||||
if (adpllj) { |
||||
sig_val = pll_sigma_delta_val(clkout_dco); |
||||
hs_mod = pll_dco_freq_sel(clkout_dco); |
||||
} |
||||
|
||||
/* by-pass pll */ |
||||
read_clkctrl = readl(&adpll->clkctrl); |
||||
writel((read_clkctrl | ADPLLJ_CLKCTRL_IDLE), &adpll->clkctrl); |
||||
while ((readl(&adpll->status) & ADPLLJ_STATUS_BYPASSANDACK) |
||||
!= ADPLLJ_STATUS_BYPASSANDACK) |
||||
; |
||||
|
||||
/* clear TINITZ */ |
||||
read_clkctrl = readl(&adpll->clkctrl); |
||||
writel((read_clkctrl & ~ADPLLJ_CLKCTRL_TINITZ), &adpll->clkctrl); |
||||
|
||||
/*
|
||||
* ref_clk = 20/(n + 1); |
||||
* clkout_dco = ref_clk * m; |
||||
* clk_out = clkout_dco/m2; |
||||
*/ |
||||
read_clkctrl = readl(&adpll->clkctrl) & |
||||
~(ADPLLJ_CLKCTRL_LPMODE | |
||||
ADPLLJ_CLKCTRL_DRIFTGUARDIAN | |
||||
ADPLLJ_CLKCTRL_REGM4XEN); |
||||
writel(m2nval, &adpll->m2ndiv); |
||||
writel(mn2val, &adpll->mn2div); |
||||
|
||||
/* Skip for modena(ADPLLS) */ |
||||
if (adpllj) { |
||||
writel(sig_val, &adpll->fracdiv); |
||||
writel((read_clkctrl | hs_mod), &adpll->clkctrl); |
||||
} |
||||
|
||||
/* Load M2, N2 dividers of ADPLL */ |
||||
writel(ADPLLJ_TENABLEDIV_ENB, &adpll->tenablediv); |
||||
writel(~ADPLLJ_TENABLEDIV_ENB, &adpll->tenablediv); |
||||
|
||||
/* Load M, N dividers of ADPLL */ |
||||
writel(ADPLLJ_TENABLE_ENB, &adpll->tenable); |
||||
writel(~ADPLLJ_TENABLE_ENB, &adpll->tenable); |
||||
|
||||
/* Configure CLKDCOLDOEN,CLKOUTLDOEN,CLKOUT Enable BITS */ |
||||
read_clkctrl = readl(&adpll->clkctrl) & ~ADPLLJ_CLKCTRL_CLKDCO; |
||||
if (adpllj) |
||||
writel((read_clkctrl | ADPLLJ_CLKCTRL_CLKDCO), |
||||
&adpll->clkctrl); |
||||
|
||||
/* Enable TINTZ and disable IDLE(PLL in Active & Locked Mode */ |
||||
read_clkctrl = readl(&adpll->clkctrl) & ~ADPLLJ_CLKCTRL_IDLE; |
||||
writel((read_clkctrl | ADPLLJ_CLKCTRL_TINITZ), &adpll->clkctrl); |
||||
|
||||
/* Wait for phase and freq lock */ |
||||
while ((readl(&adpll->status) & ADPLLJ_STATUS_PHSFRQLOCK) != |
||||
ADPLLJ_STATUS_PHSFRQLOCK) |
||||
; |
||||
} |
||||
|
||||
static void unlock_pll_control_mmr(void) |
||||
{ |
||||
/* TRM 2.10.1.4 and 3.2.7-3.2.11 */ |
||||
writel(0x1EDA4C3D, 0x481C5040); |
||||
writel(0x2FF1AC2B, 0x48140060); |
||||
writel(0xF757FDC0, 0x48140064); |
||||
writel(0xE2BC3A6D, 0x48140068); |
||||
writel(0x1EBF131D, 0x4814006c); |
||||
writel(0x6F361E05, 0x48140070); |
||||
} |
||||
|
||||
static void mpu_pll_config(void) |
||||
{ |
||||
pll_config(MPU_PLL_BASE, MPU_N, MPU_M, MPU_M2, MPU_CLKCTRL, 0); |
||||
} |
||||
|
||||
static void l3_pll_config(void) |
||||
{ |
||||
u32 l3_osc_src, rd_osc_src = 0; |
||||
|
||||
l3_osc_src = L3_OSC_SRC; |
||||
rd_osc_src = readl(OSC_SRC_CTRL); |
||||
|
||||
if (OSC_SRC0 == l3_osc_src) |
||||
writel((rd_osc_src & 0xfffffffe)|0x0, OSC_SRC_CTRL); |
||||
else |
||||
writel((rd_osc_src & 0xfffffffe)|0x1, OSC_SRC_CTRL); |
||||
|
||||
pll_config(L3_PLL_BASE, L3_N, L3_M, L3_M2, L3_CLKCTRL, 1); |
||||
} |
||||
|
||||
void ddr_pll_config(unsigned int ddrpll_m) |
||||
{ |
||||
pll_config(DDR_PLL_BASE, DDR_N, DDR_M, DDR_M2, DDR_CLKCTRL, 1); |
||||
} |
||||
|
||||
void enable_emif_clocks(void) {}; |
||||
|
||||
void enable_dmm_clocks(void) |
||||
{ |
||||
writel(PRCM_MOD_EN, &cmdef->fwclkctrl); |
||||
writel(PRCM_MOD_EN, &cmdef->l3fastclkstctrl); |
||||
writel(PRCM_MOD_EN, &cmdef->emif0clkctrl); |
||||
while ((readl(&cmdef->emif0clkctrl)) != PRCM_MOD_EN) |
||||
; |
||||
writel(PRCM_MOD_EN, &cmdef->emif1clkctrl); |
||||
while ((readl(&cmdef->emif1clkctrl)) != PRCM_MOD_EN) |
||||
; |
||||
while ((readl(&cmdef->l3fastclkstctrl) & 0x300) != 0x300) |
||||
; |
||||
writel(PRCM_MOD_EN, &cmdef->dmmclkctrl); |
||||
while ((readl(&cmdef->dmmclkctrl)) != PRCM_MOD_EN) |
||||
; |
||||
writel(PRCM_MOD_EN, &cmalwon->l3slowclkstctrl); |
||||
while ((readl(&cmalwon->l3slowclkstctrl) & 0x2100) != 0x2100) |
||||
; |
||||
} |
||||
|
||||
/*
|
||||
* Configure the PLL/PRCM for necessary peripherals |
||||
*/ |
||||
void pll_init() |
||||
{ |
||||
unlock_pll_control_mmr(); |
||||
|
||||
/* Enable the control module */ |
||||
writel(PRCM_MOD_EN, &cmalwon->controlclkctrl); |
||||
|
||||
mpu_pll_config(); |
||||
|
||||
l3_pll_config(); |
||||
|
||||
/* Enable the required peripherals */ |
||||
enable_per_clocks(); |
||||
} |
@ -0,0 +1,54 @@ |
||||
/*
|
||||
* hardware_am33xx.h |
||||
* |
||||
* AM33xx hardware specific header |
||||
* |
||||
* Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/
|
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as |
||||
* published by the Free Software Foundation; either version 2 of |
||||
* the License, or (at your option) any later version. |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#ifndef __AM33XX_HARDWARE_AM33XX_H |
||||
#define __AM33XX_HARDWARE_AM33XX_H |
||||
|
||||
/* Module base addresses */ |
||||
|
||||
/* UART Base Address */ |
||||
#define UART0_BASE 0x44E09000 |
||||
|
||||
/* GPIO Base address */ |
||||
#define GPIO2_BASE 0x481AC000 |
||||
|
||||
/* Watchdog Timer */ |
||||
#define WDT_BASE 0x44E35000 |
||||
|
||||
/* Control Module Base Address */ |
||||
#define CTRL_BASE 0x44E10000 |
||||
#define CTRL_DEVICE_BASE 0x44E10600 |
||||
|
||||
/* PRCM Base Address */ |
||||
#define PRCM_BASE 0x44E00000 |
||||
|
||||
/* VTP Base address */ |
||||
#define VTP0_CTRL_ADDR 0x44E10E0C |
||||
|
||||
/* DDR Base address */ |
||||
#define DDR_PHY_CMD_ADDR 0x44E12000 |
||||
#define DDR_PHY_DATA_ADDR 0x44E120C8 |
||||
#define DDR_DATA_REGS_NR 2 |
||||
|
||||
/* CPSW Config space */ |
||||
#define CPSW_MDIO_BASE 0x4A101000 |
||||
|
||||
/* RTC base address */ |
||||
#define RTC_BASE 0x44E3E000 |
||||
|
||||
#endif /* __AM33XX_HARDWARE_AM33XX_H */ |
@ -0,0 +1,53 @@ |
||||
/*
|
||||
* hardware_ti814x.h |
||||
* |
||||
* TI814x hardware specific header |
||||
* |
||||
* Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/
|
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as |
||||
* published by the Free Software Foundation; either version 2 of |
||||
* the License, or (at your option) any later version. |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#ifndef __AM33XX_HARDWARE_TI814X_H |
||||
#define __AM33XX_HARDWARE_TI814X_H |
||||
|
||||
/* Module base addresses */ |
||||
|
||||
/* UART Base Address */ |
||||
#define UART0_BASE 0x48020000 |
||||
|
||||
/* Watchdog Timer */ |
||||
#define WDT_BASE 0x481C7000 |
||||
|
||||
/* Control Module Base Address */ |
||||
#define CTRL_BASE 0x48140000 |
||||
|
||||
/* PRCM Base Address */ |
||||
#define PRCM_BASE 0x48180000 |
||||
|
||||
/* PLL Subsystem Base Address */ |
||||
#define PLL_SUBSYS_BASE 0x481C5000 |
||||
|
||||
/* VTP Base address */ |
||||
#define VTP0_CTRL_ADDR 0x48140E0C |
||||
|
||||
/* DDR Base address */ |
||||
#define DDR_PHY_CMD_ADDR 0x47C0C400 |
||||
#define DDR_PHY_DATA_ADDR 0x47C0C4C8 |
||||
#define DDR_DATA_REGS_NR 4 |
||||
|
||||
/* CPSW Config space */ |
||||
#define CPSW_MDIO_BASE 0x4A100800 |
||||
|
||||
/* RTC base address */ |
||||
#define RTC_BASE 0x480C0000 |
||||
|
||||
#endif /* __AM33XX_HARDWARE_TI814X_H */ |
@ -0,0 +1,247 @@ |
||||
/*
|
||||
* mux_am33xx.h |
||||
* |
||||
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as |
||||
* published by the Free Software Foundation version 2. |
||||
* |
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any |
||||
* kind, whether express or implied; without even the implied warranty |
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
*/ |
||||
|
||||
#ifndef _MUX_AM33XX_H_ |
||||
#define _MUX_AM33XX_H_ |
||||
|
||||
#include <common.h> |
||||
#include <asm/io.h> |
||||
|
||||
#define MUX_CFG(value, offset) \ |
||||
__raw_writel(value, (CTRL_BASE + offset)); |
||||
|
||||
/* PAD Control Fields */ |
||||
#define SLEWCTRL (0x1 << 6) |
||||
#define RXACTIVE (0x1 << 5) |
||||
#define PULLDOWN_EN (0x0 << 4) /* Pull Down Selection */ |
||||
#define PULLUP_EN (0x1 << 4) /* Pull Up Selection */ |
||||
#define PULLUDEN (0x0 << 3) /* Pull up enabled */ |
||||
#define PULLUDDIS (0x1 << 3) /* Pull up disabled */ |
||||
#define MODE(val) val /* used for Readability */ |
||||
|
||||
/*
|
||||
* PAD CONTROL OFFSETS |
||||
* Field names corresponds to the pad signal name |
||||
*/ |
||||
struct pad_signals { |
||||
int gpmc_ad0; |
||||
int gpmc_ad1; |
||||
int gpmc_ad2; |
||||
int gpmc_ad3; |
||||
int gpmc_ad4; |
||||
int gpmc_ad5; |
||||
int gpmc_ad6; |
||||
int gpmc_ad7; |
||||
int gpmc_ad8; |
||||
int gpmc_ad9; |
||||
int gpmc_ad10; |
||||
int gpmc_ad11; |
||||
int gpmc_ad12; |
||||
int gpmc_ad13; |
||||
int gpmc_ad14; |
||||
int gpmc_ad15; |
||||
int gpmc_a0; |
||||
int gpmc_a1; |
||||
int gpmc_a2; |
||||
int gpmc_a3; |
||||
int gpmc_a4; |
||||
int gpmc_a5; |
||||
int gpmc_a6; |
||||
int gpmc_a7; |
||||
int gpmc_a8; |
||||
int gpmc_a9; |
||||
int gpmc_a10; |
||||
int gpmc_a11; |
||||
int gpmc_wait0; |
||||
int gpmc_wpn; |
||||
int gpmc_be1n; |
||||
int gpmc_csn0; |
||||
int gpmc_csn1; |
||||
int gpmc_csn2; |
||||
int gpmc_csn3; |
||||
int gpmc_clk; |
||||
int gpmc_advn_ale; |
||||
int gpmc_oen_ren; |
||||
int gpmc_wen; |
||||
int gpmc_be0n_cle; |
||||
int lcd_data0; |
||||
int lcd_data1; |
||||
int lcd_data2; |
||||
int lcd_data3; |
||||
int lcd_data4; |
||||
int lcd_data5; |
||||
int lcd_data6; |
||||
int lcd_data7; |
||||
int lcd_data8; |
||||
int lcd_data9; |
||||
int lcd_data10; |
||||
int lcd_data11; |
||||
int lcd_data12; |
||||
int lcd_data13; |
||||
int lcd_data14; |
||||
int lcd_data15; |
||||
int lcd_vsync; |
||||
int lcd_hsync; |
||||
int lcd_pclk; |
||||
int lcd_ac_bias_en; |
||||
int mmc0_dat3; |
||||
int mmc0_dat2; |
||||
int mmc0_dat1; |
||||
int mmc0_dat0; |
||||
int mmc0_clk; |
||||
int mmc0_cmd; |
||||
int mii1_col; |
||||
int mii1_crs; |
||||
int mii1_rxerr; |
||||
int mii1_txen; |
||||
int mii1_rxdv; |
||||
int mii1_txd3; |
||||
int mii1_txd2; |
||||
int mii1_txd1; |
||||
int mii1_txd0; |
||||
int mii1_txclk; |
||||
int mii1_rxclk; |
||||
int mii1_rxd3; |
||||
int mii1_rxd2; |
||||
int mii1_rxd1; |
||||
int mii1_rxd0; |
||||
int rmii1_refclk; |
||||
int mdio_data; |
||||
int mdio_clk; |
||||
int spi0_sclk; |
||||
int spi0_d0; |
||||
int spi0_d1; |
||||
int spi0_cs0; |
||||
int spi0_cs1; |
||||
int ecap0_in_pwm0_out; |
||||
int uart0_ctsn; |
||||
int uart0_rtsn; |
||||
int uart0_rxd; |
||||
int uart0_txd; |
||||
int uart1_ctsn; |
||||
int uart1_rtsn; |
||||
int uart1_rxd; |
||||
int uart1_txd; |
||||
int i2c0_sda; |
||||
int i2c0_scl; |
||||
int mcasp0_aclkx; |
||||
int mcasp0_fsx; |
||||
int mcasp0_axr0; |
||||
int mcasp0_ahclkr; |
||||
int mcasp0_aclkr; |
||||
int mcasp0_fsr; |
||||
int mcasp0_axr1; |
||||
int mcasp0_ahclkx; |
||||
int xdma_event_intr0; |
||||
int xdma_event_intr1; |
||||
int nresetin_out; |
||||
int porz; |
||||
int nnmi; |
||||
int osc0_in; |
||||
int osc0_out; |
||||
int rsvd1; |
||||
int tms; |
||||
int tdi; |
||||
int tdo; |
||||
int tck; |
||||
int ntrst; |
||||
int emu0; |
||||
int emu1; |
||||
int osc1_in; |
||||
int osc1_out; |
||||
int pmic_power_en; |
||||
int rtc_porz; |
||||
int rsvd2; |
||||
int ext_wakeup; |
||||
int enz_kaldo_1p8v; |
||||
int usb0_dm; |
||||
int usb0_dp; |
||||
int usb0_ce; |
||||
int usb0_id; |
||||
int usb0_vbus; |
||||
int usb0_drvvbus; |
||||
int usb1_dm; |
||||
int usb1_dp; |
||||
int usb1_ce; |
||||
int usb1_id; |
||||
int usb1_vbus; |
||||
int usb1_drvvbus; |
||||
int ddr_resetn; |
||||
int ddr_csn0; |
||||
int ddr_cke; |
||||
int ddr_ck; |
||||
int ddr_nck; |
||||
int ddr_casn; |
||||
int ddr_rasn; |
||||
int ddr_wen; |
||||
int ddr_ba0; |
||||
int ddr_ba1; |
||||
int ddr_ba2; |
||||
int ddr_a0; |
||||
int ddr_a1; |
||||
int ddr_a2; |
||||
int ddr_a3; |
||||
int ddr_a4; |
||||
int ddr_a5; |
||||
int ddr_a6; |
||||
int ddr_a7; |
||||
int ddr_a8; |
||||
int ddr_a9; |
||||
int ddr_a10; |
||||
int ddr_a11; |
||||
int ddr_a12; |
||||
int ddr_a13; |
||||
int ddr_a14; |
||||
int ddr_a15; |
||||
int ddr_odt; |
||||
int ddr_d0; |
||||
int ddr_d1; |
||||
int ddr_d2; |
||||
int ddr_d3; |
||||
int ddr_d4; |
||||
int ddr_d5; |
||||
int ddr_d6; |
||||
int ddr_d7; |
||||
int ddr_d8; |
||||
int ddr_d9; |
||||
int ddr_d10; |
||||
int ddr_d11; |
||||
int ddr_d12; |
||||
int ddr_d13; |
||||
int ddr_d14; |
||||
int ddr_d15; |
||||
int ddr_dqm0; |
||||
int ddr_dqm1; |
||||
int ddr_dqs0; |
||||
int ddr_dqsn0; |
||||
int ddr_dqs1; |
||||
int ddr_dqsn1; |
||||
int ddr_vref; |
||||
int ddr_vtp; |
||||
int ddr_strben0; |
||||
int ddr_strben1; |
||||
int ain7; |
||||
int ain6; |
||||
int ain5; |
||||
int ain4; |
||||
int ain3; |
||||
int ain2; |
||||
int ain1; |
||||
int ain0; |
||||
int vrefp; |
||||
int vrefn; |
||||
}; |
||||
|
||||
#endif /* endif _MUX_AM33XX_H_ */ |
@ -0,0 +1,311 @@ |
||||
/*
|
||||
* mux_ti814x.h |
||||
* |
||||
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as |
||||
* published by the Free Software Foundation version 2. |
||||
* |
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any |
||||
* kind, whether express or implied; without even the implied warranty |
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
*/ |
||||
|
||||
#ifndef _MUX_TI814X_H_ |
||||
#define _MUX_TI814X_H_ |
||||
|
||||
/* PAD Control Fields */ |
||||
#define PINCNTL_RSV_MSK (0x3 << 18) /* Reserved bitmask */ |
||||
#define PULLUP_EN (0x1 << 17) /* Pull UP Selection */ |
||||
#define PULLUDEN (0x0 << 16) /* Pull up enabled */ |
||||
#define PULLUDDIS (0x1 << 16) /* Pull up disabled */ |
||||
#define MODE(val) val /* used for Readability */ |
||||
|
||||
#define MUX_CFG(value, offset) \ |
||||
{ \
|
||||
int tmp; \
|
||||
tmp = __raw_readl(CTRL_BASE + offset); \
|
||||
tmp &= PINCNTL_RSV_MSK; \
|
||||
__raw_writel(tmp | value, (CTRL_BASE + offset));\
|
||||
} |
||||
|
||||
/*
|
||||
* PAD CONTROL OFFSETS |
||||
* Field names corresponds to the pad signal name |
||||
*/ |
||||
struct pad_signals { |
||||
int pincntl1; |
||||
int pincntl2; |
||||
int pincntl3; |
||||
int pincntl4; |
||||
int pincntl5; |
||||
int pincntl6; |
||||
int pincntl7; |
||||
int pincntl8; |
||||
int pincntl9; |
||||
int pincntl10; |
||||
int pincntl11; |
||||
int pincntl12; |
||||
int pincntl13; |
||||
int pincntl14; |
||||
int pincntl15; |
||||
int pincntl16; |
||||
int pincntl17; |
||||
int pincntl18; |
||||
int pincntl19; |
||||
int pincntl20; |
||||
int pincntl21; |
||||
int pincntl22; |
||||
int pincntl23; |
||||
int pincntl24; |
||||
int pincntl25; |
||||
int pincntl26; |
||||
int pincntl27; |
||||
int pincntl28; |
||||
int pincntl29; |
||||
int pincntl30; |
||||
int pincntl31; |
||||
int pincntl32; |
||||
int pincntl33; |
||||
int pincntl34; |
||||
int pincntl35; |
||||
int pincntl36; |
||||
int pincntl37; |
||||
int pincntl38; |
||||
int pincntl39; |
||||
int pincntl40; |
||||
int pincntl41; |
||||
int pincntl42; |
||||
int pincntl43; |
||||
int pincntl44; |
||||
int pincntl45; |
||||
int pincntl46; |
||||
int pincntl47; |
||||
int pincntl48; |
||||
int pincntl49; |
||||
int pincntl50; |
||||
int pincntl51; |
||||
int pincntl52; |
||||
int pincntl53; |
||||
int pincntl54; |
||||
int pincntl55; |
||||
int pincntl56; |
||||
int pincntl57; |
||||
int pincntl58; |
||||
int pincntl59; |
||||
int pincntl60; |
||||
int pincntl61; |
||||
int pincntl62; |
||||
int pincntl63; |
||||
int pincntl64; |
||||
int pincntl65; |
||||
int pincntl66; |
||||
int pincntl67; |
||||
int pincntl68; |
||||
int pincntl69; |
||||
int pincntl70; |
||||
int pincntl71; |
||||
int pincntl72; |
||||
int pincntl73; |
||||
int pincntl74; |
||||
int pincntl75; |
||||
int pincntl76; |
||||
int pincntl77; |
||||
int pincntl78; |
||||
int pincntl79; |
||||
int pincntl80; |
||||
int pincntl81; |
||||
int pincntl82; |
||||
int pincntl83; |
||||
int pincntl84; |
||||
int pincntl85; |
||||
int pincntl86; |
||||
int pincntl87; |
||||
int pincntl88; |
||||
int pincntl89; |
||||
int pincntl90; |
||||
int pincntl91; |
||||
int pincntl92; |
||||
int pincntl93; |
||||
int pincntl94; |
||||
int pincntl95; |
||||
int pincntl96; |
||||
int pincntl97; |
||||
int pincntl98; |
||||
int pincntl99; |
||||
int pincntl100; |
||||
int pincntl101; |
||||
int pincntl102; |
||||
int pincntl103; |
||||
int pincntl104; |
||||
int pincntl105; |
||||
int pincntl106; |
||||
int pincntl107; |
||||
int pincntl108; |
||||
int pincntl109; |
||||
int pincntl110; |
||||
int pincntl111; |
||||
int pincntl112; |
||||
int pincntl113; |
||||
int pincntl114; |
||||
int pincntl115; |
||||
int pincntl116; |
||||
int pincntl117; |
||||
int pincntl118; |
||||
int pincntl119; |
||||
int pincntl120; |
||||
int pincntl121; |
||||
int pincntl122; |
||||
int pincntl123; |
||||
int pincntl124; |
||||
int pincntl125; |
||||
int pincntl126; |
||||
int pincntl127; |
||||
int pincntl128; |
||||
int pincntl129; |
||||
int pincntl130; |
||||
int pincntl131; |
||||
int pincntl132; |
||||
int pincntl133; |
||||
int pincntl134; |
||||
int pincntl135; |
||||
int pincntl136; |
||||
int pincntl137; |
||||
int pincntl138; |
||||
int pincntl139; |
||||
int pincntl140; |
||||
int pincntl141; |
||||
int pincntl142; |
||||
int pincntl143; |
||||
int pincntl144; |
||||
int pincntl145; |
||||
int pincntl146; |
||||
int pincntl147; |
||||
int pincntl148; |
||||
int pincntl149; |
||||
int pincntl150; |
||||
int pincntl151; |
||||
int pincntl152; |
||||
int pincntl153; |
||||
int pincntl154; |
||||
int pincntl155; |
||||
int pincntl156; |
||||
int pincntl157; |
||||
int pincntl158; |
||||
int pincntl159; |
||||
int pincntl160; |
||||
int pincntl161; |
||||
int pincntl162; |
||||
int pincntl163; |
||||
int pincntl164; |
||||
int pincntl165; |
||||
int pincntl166; |
||||
int pincntl167; |
||||
int pincntl168; |
||||
int pincntl169; |
||||
int pincntl170; |
||||
int pincntl171; |
||||
int pincntl172; |
||||
int pincntl173; |
||||
int pincntl174; |
||||
int pincntl175; |
||||
int pincntl176; |
||||
int pincntl177; |
||||
int pincntl178; |
||||
int pincntl179; |
||||
int pincntl180; |
||||
int pincntl181; |
||||
int pincntl182; |
||||
int pincntl183; |
||||
int pincntl184; |
||||
int pincntl185; |
||||
int pincntl186; |
||||
int pincntl187; |
||||
int pincntl188; |
||||
int pincntl189; |
||||
int pincntl190; |
||||
int pincntl191; |
||||
int pincntl192; |
||||
int pincntl193; |
||||
int pincntl194; |
||||
int pincntl195; |
||||
int pincntl196; |
||||
int pincntl197; |
||||
int pincntl198; |
||||
int pincntl199; |
||||
int pincntl200; |
||||
int pincntl201; |
||||
int pincntl202; |
||||
int pincntl203; |
||||
int pincntl204; |
||||
int pincntl205; |
||||
int pincntl206; |
||||
int pincntl207; |
||||
int pincntl208; |
||||
int pincntl209; |
||||
int pincntl210; |
||||
int pincntl211; |
||||
int pincntl212; |
||||
int pincntl213; |
||||
int pincntl214; |
||||
int pincntl215; |
||||
int pincntl216; |
||||
int pincntl217; |
||||
int pincntl218; |
||||
int pincntl219; |
||||
int pincntl220; |
||||
int pincntl221; |
||||
int pincntl222; |
||||
int pincntl223; |
||||
int pincntl224; |
||||
int pincntl225; |
||||
int pincntl226; |
||||
int pincntl227; |
||||
int pincntl228; |
||||
int pincntl229; |
||||
int pincntl230; |
||||
int pincntl231; |
||||
int pincntl232; |
||||
int pincntl233; |
||||
int pincntl234; |
||||
int pincntl235; |
||||
int pincntl236; |
||||
int pincntl237; |
||||
int pincntl238; |
||||
int pincntl239; |
||||
int pincntl240; |
||||
int pincntl241; |
||||
int pincntl242; |
||||
int pincntl243; |
||||
int pincntl244; |
||||
int pincntl245; |
||||
int pincntl246; |
||||
int pincntl247; |
||||
int pincntl248; |
||||
int pincntl249; |
||||
int pincntl250; |
||||
int pincntl251; |
||||
int pincntl252; |
||||
int pincntl253; |
||||
int pincntl254; |
||||
int pincntl255; |
||||
int pincntl256; |
||||
int pincntl257; |
||||
int pincntl258; |
||||
int pincntl259; |
||||
int pincntl260; |
||||
int pincntl261; |
||||
int pincntl262; |
||||
int pincntl263; |
||||
int pincntl264; |
||||
int pincntl265; |
||||
int pincntl266; |
||||
int pincntl267; |
||||
int pincntl268; |
||||
int pincntl269; |
||||
int pincntl270; |
||||
}; |
||||
|
||||
#endif /* endif _MUX_TI814X_H_ */ |
@ -0,0 +1,433 @@ |
||||
/*
|
||||
* (C) Copyright 2012 Stephen Warren |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as |
||||
* published by the Free Software Foundation; either version 2 of |
||||
* the License, or (at your option) any later version. |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#ifndef _BCM2835_MBOX_H |
||||
#define _BCM2835_MBOX_H |
||||
|
||||
#include <linux/compiler.h> |
||||
|
||||
/*
|
||||
* The BCM2835 SoC contains (at least) two CPUs; the VideoCore (a/k/a "GPU") |
||||
* and the ARM CPU. The ARM CPU is often thought of as the main CPU. |
||||
* However, the VideoCore actually controls the initial SoC boot, and hides |
||||
* much of the hardware behind a protocol. This protocol is transported |
||||
* using the SoC's mailbox hardware module. |
||||
* |
||||
* The mailbox hardware supports passing 32-bit values back and forth. |
||||
* Presumably by software convention of the firmware, the bottom 4 bits of the |
||||
* value are used to indicate a logical channel, and the upper 28 bits are the |
||||
* actual payload. Various channels exist using these simple raw messages. See |
||||
* https://github.com/raspberrypi/firmware/wiki/Mailboxes for a list. As an
|
||||
* example, the messages on the power management channel are a bitmask of |
||||
* devices whose power should be enabled. |
||||
* |
||||
* The property mailbox channel passes messages that contain the (16-byte |
||||
* aligned) ARM physical address of a memory buffer. This buffer is passed to |
||||
* the VC for processing, is modified in-place by the VC, and the address then |
||||
* passed back to the ARM CPU as the response mailbox message to indicate |
||||
* request completion. The buffers have a generic and extensible format; each |
||||
* buffer contains a standard header, a list of "tags", and a terminating zero |
||||
* entry. Each tag contains an ID indicating its type, and length fields for |
||||
* generic parsing. With some limitations, an arbitrary set of tags may be |
||||
* combined together into a single message buffer. This file defines structs |
||||
* representing the header and many individual tag layouts and IDs. |
||||
*/ |
||||
|
||||
/* Raw mailbox HW */ |
||||
|
||||
#define BCM2835_MBOX_PHYSADDR 0x2000b880 |
||||
|
||||
struct bcm2835_mbox_regs { |
||||
u32 read; |
||||
u32 rsvd0[5]; |
||||
u32 status; |
||||
u32 config; |
||||
u32 write; |
||||
}; |
||||
|
||||
#define BCM2835_MBOX_STATUS_WR_FULL 0x80000000 |
||||
#define BCM2835_MBOX_STATUS_RD_EMPTY 0x40000000 |
||||
|
||||
/* Lower 4-bits are channel ID */ |
||||
#define BCM2835_CHAN_MASK 0xf |
||||
#define BCM2835_MBOX_PACK(chan, data) (((data) & (~BCM2835_CHAN_MASK)) | \ |
||||
(chan & BCM2835_CHAN_MASK)) |
||||
#define BCM2835_MBOX_UNPACK_CHAN(val) ((val) & BCM2835_CHAN_MASK) |
||||
#define BCM2835_MBOX_UNPACK_DATA(val) ((val) & (~BCM2835_CHAN_MASK)) |
||||
|
||||
/* Property mailbox buffer structures */ |
||||
|
||||
#define BCM2835_MBOX_PROP_CHAN 8 |
||||
|
||||
/* All message buffers must start with this header */ |
||||
struct bcm2835_mbox_hdr { |
||||
u32 buf_size; |
||||
u32 code; |
||||
}; |
||||
|
||||
#define BCM2835_MBOX_REQ_CODE 0 |
||||
#define BCM2835_MBOX_RESP_CODE_SUCCESS 0x80000000 |
||||
|
||||
#define BCM2835_MBOX_INIT_HDR(_m_) { \ |
||||
memset((_m_), 0, sizeof(*(_m_))); \
|
||||
(_m_)->hdr.buf_size = sizeof(*(_m_)); \
|
||||
(_m_)->hdr.code = 0; \
|
||||
(_m_)->end_tag = 0; \
|
||||
} |
||||
|
||||
/*
|
||||
* A message buffer contains a list of tags. Each tag must also start with |
||||
* a standardized header. |
||||
*/ |
||||
struct bcm2835_mbox_tag_hdr { |
||||
u32 tag; |
||||
u32 val_buf_size; |
||||
u32 val_len; |
||||
}; |
||||
|
||||
#define BCM2835_MBOX_INIT_TAG(_t_, _id_) { \ |
||||
(_t_)->tag_hdr.tag = BCM2835_MBOX_TAG_##_id_; \
|
||||
(_t_)->tag_hdr.val_buf_size = sizeof((_t_)->body); \
|
||||
(_t_)->tag_hdr.val_len = sizeof((_t_)->body.req); \
|
||||
} |
||||
|
||||
#define BCM2835_MBOX_INIT_TAG_NO_REQ(_t_, _id_) { \ |
||||
(_t_)->tag_hdr.tag = BCM2835_MBOX_TAG_##_id_; \
|
||||
(_t_)->tag_hdr.val_buf_size = sizeof((_t_)->body); \
|
||||
(_t_)->tag_hdr.val_len = 0; \
|
||||
} |
||||
|
||||
/* When responding, the VC sets this bit in val_len to indicate a response */ |
||||
#define BCM2835_MBOX_TAG_VAL_LEN_RESPONSE 0x80000000 |
||||
|
||||
/*
|
||||
* Below we define the ID and struct for many possible tags. This header only |
||||
* defines individual tag structs, not entire message structs, since in |
||||
* general an arbitrary set of tags may be combined into a single message. |
||||
* Clients of the mbox API are expected to define their own overall message |
||||
* structures by combining the header, a set of tags, and a terminating |
||||
* entry. For example, |
||||
* |
||||
* struct msg { |
||||
* struct bcm2835_mbox_hdr hdr; |
||||
* struct bcm2835_mbox_tag_get_arm_mem get_arm_mem; |
||||
* ... perhaps other tags here ... |
||||
* u32 end_tag; |
||||
* }; |
||||
*/ |
||||
|
||||
#define BCM2835_MBOX_TAG_GET_ARM_MEMORY 0x00010005 |
||||
|
||||
struct bcm2835_mbox_tag_get_arm_mem { |
||||
struct bcm2835_mbox_tag_hdr tag_hdr; |
||||
union { |
||||
struct { |
||||
} req; |
||||
struct { |
||||
u32 mem_base; |
||||
u32 mem_size; |
||||
} resp; |
||||
} body; |
||||
}; |
||||
|
||||
#define BCM2835_MBOX_TAG_GET_CLOCK_RATE 0x00030002 |
||||
|
||||
#define BCM2835_MBOX_CLOCK_ID_EMMC 1 |
||||
#define BCM2835_MBOX_CLOCK_ID_UART 2 |
||||
#define BCM2835_MBOX_CLOCK_ID_ARM 3 |
||||
#define BCM2835_MBOX_CLOCK_ID_CORE 4 |
||||
#define BCM2835_MBOX_CLOCK_ID_V3D 5 |
||||
#define BCM2835_MBOX_CLOCK_ID_H264 6 |
||||
#define BCM2835_MBOX_CLOCK_ID_ISP 7 |
||||
#define BCM2835_MBOX_CLOCK_ID_SDRAM 8 |
||||
#define BCM2835_MBOX_CLOCK_ID_PIXEL 9 |
||||
#define BCM2835_MBOX_CLOCK_ID_PWM 10 |
||||
|
||||
struct bcm2835_mbox_tag_get_clock_rate { |
||||
struct bcm2835_mbox_tag_hdr tag_hdr; |
||||
union { |
||||
struct { |
||||
u32 clock_id; |
||||
} req; |
||||
struct { |
||||
u32 clock_id; |
||||
u32 rate_hz; |
||||
} resp; |
||||
} body; |
||||
}; |
||||
|
||||
#define BCM2835_MBOX_TAG_ALLOCATE_BUFFER 0x00040001 |
||||
|
||||
struct bcm2835_mbox_tag_allocate_buffer { |
||||
struct bcm2835_mbox_tag_hdr tag_hdr; |
||||
union { |
||||
struct { |
||||
u32 alignment; |
||||
} req; |
||||
struct { |
||||
u32 fb_address; |
||||
u32 fb_size; |
||||
} resp; |
||||
} body; |
||||
}; |
||||
|
||||
#define BCM2835_MBOX_TAG_RELEASE_BUFFER 0x00048001 |
||||
|
||||
struct bcm2835_mbox_tag_release_buffer { |
||||
struct bcm2835_mbox_tag_hdr tag_hdr; |
||||
union { |
||||
struct { |
||||
} req; |
||||
struct { |
||||
} resp; |
||||
} body; |
||||
}; |
||||
|
||||
#define BCM2835_MBOX_TAG_BLANK_SCREEN 0x00040002 |
||||
|
||||
struct bcm2835_mbox_tag_blank_screen { |
||||
struct bcm2835_mbox_tag_hdr tag_hdr; |
||||
union { |
||||
struct { |
||||
/* bit 0 means on, other bots reserved */ |
||||
u32 state; |
||||
} req; |
||||
struct { |
||||
u32 state; |
||||
} resp; |
||||
} body; |
||||
}; |
||||
|
||||
/* Physical means output signal */ |
||||
#define BCM2835_MBOX_TAG_GET_PHYSICAL_W_H 0x00040003 |
||||
#define BCM2835_MBOX_TAG_TEST_PHYSICAL_W_H 0x00044003 |
||||
#define BCM2835_MBOX_TAG_SET_PHYSICAL_W_H 0x00048003 |
||||
|
||||
struct bcm2835_mbox_tag_physical_w_h { |
||||
struct bcm2835_mbox_tag_hdr tag_hdr; |
||||
union { |
||||
/* req not used for get */ |
||||
struct { |
||||
u32 width; |
||||
u32 height; |
||||
} req; |
||||
struct { |
||||
u32 width; |
||||
u32 height; |
||||
} resp; |
||||
} body; |
||||
}; |
||||
|
||||
/* Virtual means display buffer */ |
||||
#define BCM2835_MBOX_TAG_GET_VIRTUAL_W_H 0x00040004 |
||||
#define BCM2835_MBOX_TAG_TEST_VIRTUAL_W_H 0x00044004 |
||||
#define BCM2835_MBOX_TAG_SET_VIRTUAL_W_H 0x00048004 |
||||
|
||||
struct bcm2835_mbox_tag_virtual_w_h { |
||||
struct bcm2835_mbox_tag_hdr tag_hdr; |
||||
union { |
||||
/* req not used for get */ |
||||
struct { |
||||
u32 width; |
||||
u32 height; |
||||
} req; |
||||
struct { |
||||
u32 width; |
||||
u32 height; |
||||
} resp; |
||||
} body; |
||||
}; |
||||
|
||||
#define BCM2835_MBOX_TAG_GET_DEPTH 0x00040005 |
||||
#define BCM2835_MBOX_TAG_TEST_DEPTH 0x00044005 |
||||
#define BCM2835_MBOX_TAG_SET_DEPTH 0x00048005 |
||||
|
||||
struct bcm2835_mbox_tag_depth { |
||||
struct bcm2835_mbox_tag_hdr tag_hdr; |
||||
union { |
||||
/* req not used for get */ |
||||
struct { |
||||
u32 bpp; |
||||
} req; |
||||
struct { |
||||
u32 bpp; |
||||
} resp; |
||||
} body; |
||||
}; |
||||
|
||||
#define BCM2835_MBOX_TAG_GET_PIXEL_ORDER 0x00040006 |
||||
#define BCM2835_MBOX_TAG_TEST_PIXEL_ORDER 0x00044005 |
||||
#define BCM2835_MBOX_TAG_SET_PIXEL_ORDER 0x00048006 |
||||
|
||||
#define BCM2835_MBOX_PIXEL_ORDER_BGR 0 |
||||
#define BCM2835_MBOX_PIXEL_ORDER_RGB 1 |
||||
|
||||
struct bcm2835_mbox_tag_pixel_order { |
||||
struct bcm2835_mbox_tag_hdr tag_hdr; |
||||
union { |
||||
/* req not used for get */ |
||||
struct { |
||||
u32 order; |
||||
} req; |
||||
struct { |
||||
u32 order; |
||||
} resp; |
||||
} body; |
||||
}; |
||||
|
||||
#define BCM2835_MBOX_TAG_GET_ALPHA_MODE 0x00040007 |
||||
#define BCM2835_MBOX_TAG_TEST_ALPHA_MODE 0x00044007 |
||||
#define BCM2835_MBOX_TAG_SET_ALPHA_MODE 0x00048007 |
||||
|
||||
#define BCM2835_MBOX_ALPHA_MODE_0_OPAQUE 0 |
||||
#define BCM2835_MBOX_ALPHA_MODE_0_TRANSPARENT 1 |
||||
#define BCM2835_MBOX_ALPHA_MODE_IGNORED 2 |
||||
|
||||
struct bcm2835_mbox_tag_alpha_mode { |
||||
struct bcm2835_mbox_tag_hdr tag_hdr; |
||||
union { |
||||
/* req not used for get */ |
||||
struct { |
||||
u32 alpha; |
||||
} req; |
||||
struct { |
||||
u32 alpha; |
||||
} resp; |
||||
} body; |
||||
}; |
||||
|
||||
#define BCM2835_MBOX_TAG_GET_PITCH 0x00040008 |
||||
|
||||
struct bcm2835_mbox_tag_pitch { |
||||
struct bcm2835_mbox_tag_hdr tag_hdr; |
||||
union { |
||||
struct { |
||||
} req; |
||||
struct { |
||||
u32 pitch; |
||||
} resp; |
||||
} body; |
||||
}; |
||||
|
||||
/* Offset of display window within buffer */ |
||||
#define BCM2835_MBOX_TAG_GET_VIRTUAL_OFFSET 0x00040009 |
||||
#define BCM2835_MBOX_TAG_TEST_VIRTUAL_OFFSET 0x00044009 |
||||
#define BCM2835_MBOX_TAG_SET_VIRTUAL_OFFSET 0x00048009 |
||||
|
||||
struct bcm2835_mbox_tag_virtual_offset { |
||||
struct bcm2835_mbox_tag_hdr tag_hdr; |
||||
union { |
||||
/* req not used for get */ |
||||
struct { |
||||
u32 x; |
||||
u32 y; |
||||
} req; |
||||
struct { |
||||
u32 x; |
||||
u32 y; |
||||
} resp; |
||||
} body; |
||||
}; |
||||
|
||||
#define BCM2835_MBOX_TAG_GET_OVERSCAN 0x0004000a |
||||
#define BCM2835_MBOX_TAG_TEST_OVERSCAN 0x0004400a |
||||
#define BCM2835_MBOX_TAG_SET_OVERSCAN 0x0004800a |
||||
|
||||
struct bcm2835_mbox_tag_overscan { |
||||
struct bcm2835_mbox_tag_hdr tag_hdr; |
||||
union { |
||||
/* req not used for get */ |
||||
struct { |
||||
u32 top; |
||||
u32 bottom; |
||||
u32 left; |
||||
u32 right; |
||||
} req; |
||||
struct { |
||||
u32 top; |
||||
u32 bottom; |
||||
u32 left; |
||||
} resp; |
||||
} body; |
||||
}; |
||||
|
||||
#define BCM2835_MBOX_TAG_GET_PALETTE 0x0004000b |
||||
|
||||
struct bcm2835_mbox_tag_get_palette { |
||||
struct bcm2835_mbox_tag_hdr tag_hdr; |
||||
union { |
||||
struct { |
||||
} req; |
||||
struct { |
||||
u32 data[1024]; |
||||
} resp; |
||||
} body; |
||||
}; |
||||
|
||||
#define BCM2835_MBOX_TAG_TEST_PALETTE 0x0004400b |
||||
|
||||
struct bcm2835_mbox_tag_test_palette { |
||||
struct bcm2835_mbox_tag_hdr tag_hdr; |
||||
union { |
||||
struct { |
||||
u32 offset; |
||||
u32 num_entries; |
||||
u32 data[256]; |
||||
} req; |
||||
struct { |
||||
u32 is_invalid; |
||||
} resp; |
||||
} body; |
||||
}; |
||||
|
||||
#define BCM2835_MBOX_TAG_SET_PALETTE 0x0004800b |
||||
|
||||
struct bcm2835_mbox_tag_set_palette { |
||||
struct bcm2835_mbox_tag_hdr tag_hdr; |
||||
union { |
||||
struct { |
||||
u32 offset; |
||||
u32 num_entries; |
||||
u32 data[256]; |
||||
} req; |
||||
struct { |
||||
u32 is_invalid; |
||||
} resp; |
||||
} body; |
||||
}; |
||||
|
||||
/*
|
||||
* Pass a raw u32 message to the VC, and receive a raw u32 back. |
||||
* |
||||
* Returns 0 for success, any other value for error. |
||||
*/ |
||||
int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv); |
||||
|
||||
/*
|
||||
* Pass a complete property-style buffer to the VC, and wait until it has |
||||
* been processed. |
||||
* |
||||
* This function expects a pointer to the mbox_hdr structure in an attempt |
||||
* to ensure some degree of type safety. However, some number of tags and |
||||
* a termination value are expected to immediately follow the header in |
||||
* memory, as required by the property protocol. |
||||
* |
||||
* Returns 0 for success, any other value for error. |
||||
*/ |
||||
int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_hdr *buffer); |
||||
|
||||
#endif |
@ -0,0 +1,24 @@ |
||||
/*
|
||||
* (C) Copyright 2012 Stephen Warren |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#ifndef _BCM2835_SDHCI_H_ |
||||
#define _BCM2835_SDHCI_H_ |
||||
|
||||
#define BCM2835_SDHCI_BASE 0x20300000 |
||||
|
||||
int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq); |
||||
|
||||
#endif |
@ -0,0 +1,58 @@ |
||||
/*
|
||||
* Copyright (c) 2012 Samsung Electronics Co., Ltd. |
||||
* http://www.samsung.com
|
||||
* Akshay Saraswat <akshay.s@samsung.com> |
||||
* |
||||
* EXYNOS - Thermal Management Unit |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* 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. |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||
* MA 02111-1307 USA |
||||
*/ |
||||
|
||||
#ifndef __ASM_ARCH_TMU_H |
||||
#define __ASM_ARCH_TMU_H |
||||
|
||||
struct exynos5_tmu_reg { |
||||
unsigned triminfo; |
||||
unsigned rsvd1; |
||||
unsigned rsvd2; |
||||
unsigned rsvd3; |
||||
unsigned rsvd4; |
||||
unsigned triminfo_control; |
||||
unsigned rsvd5; |
||||
unsigned rsvd6; |
||||
unsigned tmu_control; |
||||
unsigned rsvd7; |
||||
unsigned tmu_status; |
||||
unsigned sampling_internal; |
||||
unsigned counter_value0; |
||||
unsigned counter_value1; |
||||
unsigned rsvd8; |
||||
unsigned rsvd9; |
||||
unsigned current_temp; |
||||
unsigned rsvd10; |
||||
unsigned rsvd11; |
||||
unsigned rsvd12; |
||||
unsigned threshold_temp_rise; |
||||
unsigned threshold_temp_fall; |
||||
unsigned rsvd13; |
||||
unsigned rsvd14; |
||||
unsigned past_temp3_0; |
||||
unsigned past_temp7_4; |
||||
unsigned past_temp11_8; |
||||
unsigned past_temp15_12; |
||||
unsigned inten; |
||||
unsigned intstat; |
||||
unsigned intclear; |
||||
unsigned rsvd15; |
||||
unsigned emul_con; |
||||
}; |
||||
#endif /* __ASM_ARCH_TMU_H */ |
@ -1,84 +0,0 @@ |
||||
/*
|
||||
* NVIDIA Tegra SPI-SLINK controller |
||||
* |
||||
* Copyright 2010-2013 NVIDIA Corporation |
||||
* |
||||
* This software may be used and distributed according to the |
||||
* terms of the GNU Public License, Version 2, incorporated |
||||
* herein by reference. |
||||
* |
||||
* 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, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||
* MA 02111-1307 USA |
||||
*/ |
||||
|
||||
#ifndef _TEGRA_SLINK_H_ |
||||
#define _TEGRA_SLINK_H_ |
||||
|
||||
#include <asm/types.h> |
||||
|
||||
struct slink_tegra { |
||||
u32 command; /* SLINK_COMMAND_0 register */ |
||||
u32 command2; /* SLINK_COMMAND2_0 reg */ |
||||
u32 status; /* SLINK_STATUS_0 register */ |
||||
u32 reserved; /* Reserved offset 0C */ |
||||
u32 mas_data; /* SLINK_MAS_DATA_0 reg */ |
||||
u32 slav_data; /* SLINK_SLAVE_DATA_0 reg */ |
||||
u32 dma_ctl; /* SLINK_DMA_CTL_0 register */ |
||||
u32 status2; /* SLINK_STATUS2_0 reg */ |
||||
u32 rsvd[56]; /* 0x20 to 0xFF reserved */ |
||||
u32 tx_fifo; /* SLINK_TX_FIFO_0 reg off 100h */ |
||||
u32 rsvd2[31]; /* 0x104 to 0x17F reserved */ |
||||
u32 rx_fifo; /* SLINK_RX_FIFO_0 reg off 180h */ |
||||
}; |
||||
|
||||
/* COMMAND */ |
||||
#define SLINK_CMD_ENB (1 << 31) |
||||
#define SLINK_CMD_GO (1 << 30) |
||||
#define SLINK_CMD_M_S (1 << 28) |
||||
#define SLINK_CMD_CK_SDA (1 << 21) |
||||
#define SLINK_CMD_CS_POL (1 << 13) |
||||
#define SLINK_CMD_CS_VAL (1 << 12) |
||||
#define SLINK_CMD_CS_SOFT (1 << 11) |
||||
#define SLINK_CMD_BIT_LENGTH (1 << 4) |
||||
#define SLINK_CMD_BIT_LENGTH_MASK 0x0000001F |
||||
/* COMMAND2 */ |
||||
#define SLINK_CMD2_TXEN (1 << 30) |
||||
#define SLINK_CMD2_RXEN (1 << 31) |
||||
#define SLINK_CMD2_SS_EN (1 << 18) |
||||
#define SLINK_CMD2_SS_EN_SHIFT 18 |
||||
#define SLINK_CMD2_SS_EN_MASK 0x000C0000 |
||||
#define SLINK_CMD2_CS_ACTIVE_BETWEEN (1 << 17) |
||||
/* STATUS */ |
||||
#define SLINK_STAT_BSY (1 << 31) |
||||
#define SLINK_STAT_RDY (1 << 30) |
||||
#define SLINK_STAT_ERR (1 << 29) |
||||
#define SLINK_STAT_RXF_FLUSH (1 << 27) |
||||
#define SLINK_STAT_TXF_FLUSH (1 << 26) |
||||
#define SLINK_STAT_RXF_OVF (1 << 25) |
||||
#define SLINK_STAT_TXF_UNR (1 << 24) |
||||
#define SLINK_STAT_RXF_EMPTY (1 << 23) |
||||
#define SLINK_STAT_RXF_FULL (1 << 22) |
||||
#define SLINK_STAT_TXF_EMPTY (1 << 21) |
||||
#define SLINK_STAT_TXF_FULL (1 << 20) |
||||
#define SLINK_STAT_TXF_OVF (1 << 19) |
||||
#define SLINK_STAT_RXF_UNR (1 << 18) |
||||
#define SLINK_STAT_CUR_BLKCNT (1 << 15) |
||||
/* STATUS2 */ |
||||
#define SLINK_STAT2_RXF_FULL_CNT (1 << 16) |
||||
#define SLINK_STAT2_TXF_FULL_CNT (1 << 0) |
||||
|
||||
#define SPI_TIMEOUT 1000 |
||||
#define TEGRA_SPI_MAX_FREQ 52000000 |
||||
|
||||
#endif /* _TEGRA_SLINK_H_ */ |
@ -1,75 +0,0 @@ |
||||
/*
|
||||
* NVIDIA Tegra20 SPI-FLASH controller |
||||
* |
||||
* Copyright 2010-2012 NVIDIA Corporation |
||||
* |
||||
* This software may be used and distributed according to the |
||||
* terms of the GNU Public License, Version 2, incorporated |
||||
* herein by reference. |
||||
* |
||||
* 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, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||
* MA 02111-1307 USA |
||||
*/ |
||||
|
||||
#ifndef _TEGRA_SPI_H_ |
||||
#define _TEGRA_SPI_H_ |
||||
|
||||
#include <asm/types.h> |
||||
|
||||
struct spi_tegra { |
||||
u32 command; /* SPI_COMMAND_0 register */ |
||||
u32 status; /* SPI_STATUS_0 register */ |
||||
u32 rx_cmp; /* SPI_RX_CMP_0 register */ |
||||
u32 dma_ctl; /* SPI_DMA_CTL_0 register */ |
||||
u32 tx_fifo; /* SPI_TX_FIFO_0 register */ |
||||
u32 rsvd[3]; /* offsets 0x14 to 0x1F reserved */ |
||||
u32 rx_fifo; /* SPI_RX_FIFO_0 register */ |
||||
}; |
||||
|
||||
#define SPI_CMD_GO (1 << 30) |
||||
#define SPI_CMD_ACTIVE_SCLK_SHIFT 26 |
||||
#define SPI_CMD_ACTIVE_SCLK_MASK (3 << SPI_CMD_ACTIVE_SCLK_SHIFT) |
||||
#define SPI_CMD_CK_SDA (1 << 21) |
||||
#define SPI_CMD_ACTIVE_SDA_SHIFT 18 |
||||
#define SPI_CMD_ACTIVE_SDA_MASK (3 << SPI_CMD_ACTIVE_SDA_SHIFT) |
||||
#define SPI_CMD_CS_POL (1 << 16) |
||||
#define SPI_CMD_TXEN (1 << 15) |
||||
#define SPI_CMD_RXEN (1 << 14) |
||||
#define SPI_CMD_CS_VAL (1 << 13) |
||||
#define SPI_CMD_CS_SOFT (1 << 12) |
||||
#define SPI_CMD_CS_DELAY (1 << 9) |
||||
#define SPI_CMD_CS3_EN (1 << 8) |
||||
#define SPI_CMD_CS2_EN (1 << 7) |
||||
#define SPI_CMD_CS1_EN (1 << 6) |
||||
#define SPI_CMD_CS0_EN (1 << 5) |
||||
#define SPI_CMD_BIT_LENGTH (1 << 4) |
||||
#define SPI_CMD_BIT_LENGTH_MASK 0x0000001F |
||||
|
||||
#define SPI_STAT_BSY (1 << 31) |
||||
#define SPI_STAT_RDY (1 << 30) |
||||
#define SPI_STAT_RXF_FLUSH (1 << 29) |
||||
#define SPI_STAT_TXF_FLUSH (1 << 28) |
||||
#define SPI_STAT_RXF_UNR (1 << 27) |
||||
#define SPI_STAT_TXF_OVF (1 << 26) |
||||
#define SPI_STAT_RXF_EMPTY (1 << 25) |
||||
#define SPI_STAT_RXF_FULL (1 << 24) |
||||
#define SPI_STAT_TXF_EMPTY (1 << 23) |
||||
#define SPI_STAT_TXF_FULL (1 << 22) |
||||
#define SPI_STAT_SEL_TXRX_N (1 << 16) |
||||
#define SPI_STAT_CUR_BLKCNT (1 << 15) |
||||
|
||||
#define SPI_TIMEOUT 1000 |
||||
#define TEGRA_SPI_MAX_FREQ 52000000 |
||||
|
||||
#endif /* _TEGRA_SPI_H_ */ |
@ -0,0 +1,41 @@ |
||||
/*
|
||||
* NVIDIA Tegra SPI controller |
||||
* |
||||
* Copyright 2010-2013 NVIDIA Corporation |
||||
* |
||||
* This software may be used and distributed according to the |
||||
* terms of the GNU Public License, Version 2, incorporated |
||||
* herein by reference. |
||||
* |
||||
* 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, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||
* MA 02111-1307 USA |
||||
*/ |
||||
|
||||
#ifndef _TEGRA114_SPI_H_ |
||||
#define _TEGRA114_SPI_H_ |
||||
|
||||
#include <asm/types.h> |
||||
|
||||
int tegra114_spi_init(int *node_list, int count); |
||||
int tegra114_spi_cs_is_valid(unsigned int bus, unsigned int cs); |
||||
struct spi_slave *tegra114_spi_setup_slave(unsigned int bus, unsigned int cs, |
||||
unsigned int max_hz, unsigned int mode); |
||||
void tegra114_spi_free_slave(struct spi_slave *slave); |
||||
int tegra114_spi_claim_bus(struct spi_slave *slave); |
||||
void tegra114_spi_cs_activate(struct spi_slave *slave); |
||||
void tegra114_spi_cs_deactivate(struct spi_slave *slave); |
||||
int tegra114_spi_xfer(struct spi_slave *slave, unsigned int bitlen, |
||||
const void *data_out, void *data_in, unsigned long flags); |
||||
|
||||
#endif /* _TEGRA114_SPI_H_ */ |
@ -0,0 +1,41 @@ |
||||
/*
|
||||
* NVIDIA Tegra20 SPI-FLASH controller |
||||
* |
||||
* Copyright 2010-2012 NVIDIA Corporation |
||||
* |
||||
* This software may be used and distributed according to the |
||||
* terms of the GNU Public License, Version 2, incorporated |
||||
* herein by reference. |
||||
* |
||||
* 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, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||
* MA 02111-1307 USA |
||||
*/ |
||||
|
||||
#ifndef _TEGRA20_SPI_H_ |
||||
#define _TEGRA20_SPI_H_ |
||||
|
||||
#include <asm/types.h> |
||||
|
||||
int tegra20_spi_cs_is_valid(unsigned int bus, unsigned int cs); |
||||
struct spi_slave *tegra20_spi_setup_slave(unsigned int bus, unsigned int cs, |
||||
unsigned int max_hz, unsigned int mode); |
||||
void tegra20_spi_free_slave(struct spi_slave *slave); |
||||
int tegra20_spi_init(int *node_list, int count); |
||||
int tegra20_spi_claim_bus(struct spi_slave *slave); |
||||
void tegra20_spi_cs_activate(struct spi_slave *slave); |
||||
void tegra20_spi_cs_deactivate(struct spi_slave *slave); |
||||
int tegra20_spi_xfer(struct spi_slave *slave, unsigned int bitlen, |
||||
const void *data_out, void *data_in, unsigned long flags); |
||||
|
||||
#endif /* _TEGRA20_SPI_H_ */ |
@ -0,0 +1,41 @@ |
||||
/*
|
||||
* NVIDIA Tegra SPI-SLINK controller |
||||
* |
||||
* Copyright 2010-2013 NVIDIA Corporation |
||||
* |
||||
* This software may be used and distributed according to the |
||||
* terms of the GNU Public License, Version 2, incorporated |
||||
* herein by reference. |
||||
* |
||||
* 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, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||
* MA 02111-1307 USA |
||||
*/ |
||||
|
||||
#ifndef _TEGRA30_SPI_H_ |
||||
#define _TEGRA30_SPI_H_ |
||||
|
||||
#include <asm/types.h> |
||||
|
||||
int tegra30_spi_init(int *node_list, int count); |
||||
int tegra30_spi_cs_is_valid(unsigned int bus, unsigned int cs); |
||||
struct spi_slave *tegra30_spi_setup_slave(unsigned int bus, unsigned int cs, |
||||
unsigned int max_hz, unsigned int mode); |
||||
void tegra30_spi_free_slave(struct spi_slave *slave); |
||||
int tegra30_spi_claim_bus(struct spi_slave *slave); |
||||
void tegra30_spi_cs_activate(struct spi_slave *slave); |
||||
void tegra30_spi_cs_deactivate(struct spi_slave *slave); |
||||
int tegra30_spi_xfer(struct spi_slave *slave, unsigned int bitlen, |
||||
const void *data_out, void *data_in, unsigned long flags); |
||||
|
||||
#endif /* _TEGRA30_SPI_H_ */ |
@ -1,4 +1,3 @@ |
||||
# common options for all tegra boards
|
||||
COBJS-y += ../../nvidia/common/board.o
|
||||
COBJS-$(CONFIG_SPI_UART_SWITCH) += ../../nvidia/common/uart-spi-switch.o
|
||||
COBJS-$(CONFIG_TEGRA_CLOCK_SCALING) += ../../nvidia/common/emc.o
|
||||
|
@ -1,125 +0,0 @@ |
||||
/*
|
||||
* Copyright (c) 2011 The Chromium OS Authors. |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as |
||||
* published by the Free Software Foundation; either version 2 of |
||||
* the License, or (at your option) any later version. |
||||
* |
||||
* 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, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||
* MA 02111-1307 USA |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <asm/gpio.h> |
||||
#include <asm/arch/pinmux.h> |
||||
#include <asm/arch/uart-spi-switch.h> |
||||
#include <asm/arch/tegra.h> |
||||
#include <asm/arch-tegra/tegra_spi.h> |
||||
#include <asm/arch-tegra/board.h> |
||||
|
||||
/* position of the UART/SPI select switch */ |
||||
enum spi_uart_switch { |
||||
SWITCH_UNKNOWN, |
||||
SWITCH_SPI, |
||||
SWITCH_UART, |
||||
SWITCH_BOTH |
||||
}; |
||||
|
||||
/* Information about the spi/uart switch */ |
||||
struct spi_uart { |
||||
int gpio; /* GPIO to control switch */ |
||||
u32 port; /* Port number of UART affected */ |
||||
}; |
||||
|
||||
static struct spi_uart local; |
||||
static enum spi_uart_switch switch_pos; /* Current switch position */ |
||||
|
||||
|
||||
static void get_config(struct spi_uart *config) |
||||
{ |
||||
#if defined CONFIG_SPI_CORRUPTS_UART |
||||
config->gpio = CONFIG_UART_DISABLE_GPIO; |
||||
config->port = CONFIG_SPI_CORRUPTS_UART_NR; |
||||
#else |
||||
config->gpio = -1; |
||||
#endif |
||||
} |
||||
|
||||
/*
|
||||
* Init the UART / SPI switch. This can be called before relocation so we must |
||||
* not access BSS. |
||||
*/ |
||||
void gpio_early_init_uart(void) |
||||
{ |
||||
struct spi_uart config; |
||||
|
||||
get_config(&config); |
||||
if (config.gpio != -1) { |
||||
/* Cannot provide a label prior to relocation */ |
||||
gpio_request(config.gpio, NULL); |
||||
gpio_direction_output(config.gpio, 0); |
||||
} |
||||
} |
||||
|
||||
/*
|
||||
* Configure the UART / SPI switch. |
||||
*/ |
||||
void gpio_config_uart(void) |
||||
{ |
||||
get_config(&local); |
||||
if (local.gpio != -1) { |
||||
gpio_direction_output(local.gpio, 0); |
||||
switch_pos = SWITCH_UART; |
||||
} else { |
||||
/*
|
||||
* If we're here we don't have a SPI switch; go ahead and |
||||
* enable the SPI now. We didn't in spi_init() so we wouldn't |
||||
* kill the UART. |
||||
*/ |
||||
pinmux_set_func(PINGRP_GMC, PMUX_FUNC_SFLASH); |
||||
switch_pos = SWITCH_BOTH; |
||||
} |
||||
} |
||||
|
||||
static void spi_uart_switch(struct spi_uart *config, |
||||
enum spi_uart_switch new_pos) |
||||
{ |
||||
if (switch_pos == SWITCH_BOTH || new_pos == switch_pos) |
||||
return; |
||||
|
||||
/* pre-delay, allow SPI/UART to settle, FIFO to empty, etc. */ |
||||
udelay(CONFIG_SPI_CORRUPTS_UART_DLY); |
||||
|
||||
/* We need to dynamically change the pinmux, shared w/UART RXD/CTS */ |
||||
pinmux_set_func(PINGRP_GMC, new_pos == SWITCH_SPI ? |
||||
PMUX_FUNC_SFLASH : PMUX_FUNC_UARTD); |
||||
|
||||
/*
|
||||
* On Seaboard, MOSI/MISO are shared w/UART. |
||||
* Use GPIO I3 (UART_DISABLE) to tristate UART during SPI activity. |
||||
* Enable UART later (cs_deactivate) so we can use it for U-Boot comms. |
||||
*/ |
||||
gpio_direction_output(config->gpio, new_pos == SWITCH_SPI); |
||||
switch_pos = new_pos; |
||||
} |
||||
|
||||
void pinmux_select_uart(void) |
||||
{ |
||||
spi_uart_switch(&local, SWITCH_UART); |
||||
} |
||||
|
||||
void pinmux_select_spi(void) |
||||
{ |
||||
spi_uart_switch(&local, SWITCH_SPI); |
||||
} |
@ -0,0 +1,58 @@ |
||||
/* |
||||
* SAMSUNG Snow board device tree source |
||||
* |
||||
* Copyright (c) 2012 Samsung Electronics Co., Ltd. |
||||
* http://www.samsung.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. |
||||
*/ |
||||
|
||||
/dts-v1/; |
||||
/include/ ARCH_CPU_DTS |
||||
|
||||
/ { |
||||
model = "Google Snow"; |
||||
compatible = "google,snow", "samsung,exynos5250"; |
||||
|
||||
aliases { |
||||
i2c0 = "/i2c@12c60000"; |
||||
i2c1 = "/i2c@12c70000"; |
||||
i2c2 = "/i2c@12c80000"; |
||||
i2c3 = "/i2c@12c90000"; |
||||
i2c4 = "/i2c@12ca0000"; |
||||
i2c5 = "/i2c@12cb0000"; |
||||
i2c6 = "/i2c@12cc0000"; |
||||
i2c7 = "/i2c@12cd0000"; |
||||
spi0 = "/spi@12d20000"; |
||||
spi1 = "/spi@12d30000"; |
||||
spi2 = "/spi@12d40000"; |
||||
spi3 = "/spi@131a0000"; |
||||
spi4 = "/spi@131b0000"; |
||||
}; |
||||
|
||||
sound@12d60000 { |
||||
samsung,i2s-epll-clock-frequency = <192000000>; |
||||
samsung,i2s-sampling-rate = <48000>; |
||||
samsung,i2s-bits-per-sample = <16>; |
||||
samsung,i2s-channels = <2>; |
||||
samsung,i2s-lr-clk-framesize = <256>; |
||||
samsung,i2s-bit-clk-framesize = <32>; |
||||
samsung,codec-type = "max98095"; |
||||
}; |
||||
|
||||
i2c@12cd0000 { |
||||
soundcodec@22 { |
||||
reg = <0x22>; |
||||
compatible = "maxim,max98095-codec"; |
||||
}; |
||||
}; |
||||
|
||||
i2c@12c60000 { |
||||
pmic@9 { |
||||
reg = <0x9>; |
||||
compatible = "maxim,max77686_pmic"; |
||||
}; |
||||
}; |
||||
}; |
@ -0,0 +1,46 @@ |
||||
#
|
||||
# Makefile
|
||||
#
|
||||
# Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
||||
# kind, whether express or implied; without even the implied warranty
|
||||
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/config.mk |
||||
|
||||
LIB = $(obj)lib$(BOARD).o
|
||||
|
||||
ifdef CONFIG_SPL_BUILD |
||||
COBJS := mux.o
|
||||
endif |
||||
|
||||
COBJS += evm.o
|
||||
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(COBJS))
|
||||
SOBJS := $(addprefix $(obj),$(SOBJS))
|
||||
|
||||
$(LIB): $(obj).depend $(OBJS) $(SOBJS) |
||||
$(call cmd_link_o_target, $(OBJS) $(SOBJS))
|
||||
|
||||
clean: |
||||
rm -f $(SOBJS) $(OBJS)
|
||||
|
||||
distclean: clean |
||||
rm -f $(LIB) core *.bak $(obj).depend
|
||||
|
||||
#########################################################################
|
||||
|
||||
# defines $(obj).depend target
|
||||
include $(SRCTREE)/rules.mk |
||||
|
||||
sinclude $(obj).depend |
||||
|
||||
#########################################################################
|
@ -0,0 +1,198 @@ |
||||
/*
|
||||
* evm.c |
||||
* |
||||
* Board functions for TI814x EVM |
||||
* |
||||
* Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/
|
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as |
||||
* published by the Free Software Foundation; either version 2 of |
||||
* the License, or (at your option) any later version. |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <errno.h> |
||||
#include <spl.h> |
||||
#include <asm/arch/cpu.h> |
||||
#include <asm/arch/hardware.h> |
||||
#include <asm/arch/omap.h> |
||||
#include <asm/arch/ddr_defs.h> |
||||
#include <asm/arch/clock.h> |
||||
#include <asm/arch/gpio.h> |
||||
#include <asm/arch/mmc_host_def.h> |
||||
#include <asm/arch/sys_proto.h> |
||||
#include <asm/io.h> |
||||
#include <asm/emif.h> |
||||
#include <asm/gpio.h> |
||||
#include "evm.h" |
||||
|
||||
DECLARE_GLOBAL_DATA_PTR; |
||||
|
||||
#ifdef CONFIG_SPL_BUILD |
||||
static struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE; |
||||
static struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE; |
||||
#endif |
||||
|
||||
/* UART Defines */ |
||||
#ifdef CONFIG_SPL_BUILD |
||||
#define UART_RESET (0x1 << 1) |
||||
#define UART_CLK_RUNNING_MASK 0x1 |
||||
#define UART_SMART_IDLE_EN (0x1 << 0x3) |
||||
|
||||
static void rtc32k_enable(void) |
||||
{ |
||||
struct rtc_regs *rtc = (struct rtc_regs *)RTC_BASE; |
||||
|
||||
/*
|
||||
* Unlock the RTC's registers. For more details please see the |
||||
* RTC_SS section of the TRM. In order to unlock we need to |
||||
* write these specific values (keys) in this order. |
||||
*/ |
||||
writel(0x83e70b13, &rtc->kick0r); |
||||
writel(0x95a4f1e0, &rtc->kick1r); |
||||
|
||||
/* Enable the RTC 32K OSC by setting bits 3 and 6. */ |
||||
writel((1 << 3) | (1 << 6), &rtc->osc); |
||||
} |
||||
|
||||
static void uart_enable(void) |
||||
{ |
||||
u32 regVal; |
||||
|
||||
/* UART softreset */ |
||||
regVal = readl(&uart_base->uartsyscfg); |
||||
regVal |= UART_RESET; |
||||
writel(regVal, &uart_base->uartsyscfg); |
||||
while ((readl(&uart_base->uartsyssts) & |
||||
UART_CLK_RUNNING_MASK) != UART_CLK_RUNNING_MASK) |
||||
; |
||||
|
||||
/* Disable smart idle */ |
||||
regVal = readl(&uart_base->uartsyscfg); |
||||
regVal |= UART_SMART_IDLE_EN; |
||||
writel(regVal, &uart_base->uartsyscfg); |
||||
} |
||||
|
||||
static void wdt_disable(void) |
||||
{ |
||||
writel(0xAAAA, &wdtimer->wdtwspr); |
||||
while (readl(&wdtimer->wdtwwps) != 0x0) |
||||
; |
||||
writel(0x5555, &wdtimer->wdtwspr); |
||||
while (readl(&wdtimer->wdtwwps) != 0x0) |
||||
; |
||||
} |
||||
|
||||
static const struct cmd_control evm_ddr2_cctrl_data = { |
||||
.cmd0csratio = 0x80, |
||||
.cmd0dldiff = 0x04, |
||||
.cmd0iclkout = 0x00, |
||||
|
||||
.cmd1csratio = 0x80, |
||||
.cmd1dldiff = 0x04, |
||||
.cmd1iclkout = 0x00, |
||||
|
||||
.cmd2csratio = 0x80, |
||||
.cmd2dldiff = 0x04, |
||||
.cmd2iclkout = 0x00, |
||||
}; |
||||
|
||||
static const struct emif_regs evm_ddr2_emif0_regs = { |
||||
.sdram_config = 0x40801ab2, |
||||
.ref_ctrl = 0x10000c30, |
||||
.sdram_tim1 = 0x0aaaf552, |
||||
.sdram_tim2 = 0x043631d2, |
||||
.sdram_tim3 = 0x00000327, |
||||
.emif_ddr_phy_ctlr_1 = 0x00000007 |
||||
}; |
||||
|
||||
static const struct emif_regs evm_ddr2_emif1_regs = { |
||||
.sdram_config = 0x40801ab2, |
||||
.ref_ctrl = 0x10000c30, |
||||
.sdram_tim1 = 0x0aaaf552, |
||||
.sdram_tim2 = 0x043631d2, |
||||
.sdram_tim3 = 0x00000327, |
||||
.emif_ddr_phy_ctlr_1 = 0x00000007 |
||||
}; |
||||
|
||||
const struct dmm_lisa_map_regs evm_lisa_map_regs = { |
||||
.dmm_lisa_map_0 = 0x00000000, |
||||
.dmm_lisa_map_1 = 0x00000000, |
||||
.dmm_lisa_map_2 = 0x806c0300, |
||||
.dmm_lisa_map_3 = 0x806c0300, |
||||
}; |
||||
|
||||
static const struct ddr_data evm_ddr2_data = { |
||||
.datardsratio0 = ((0x35<<10) | (0x35<<0)), |
||||
.datawdsratio0 = ((0x20<<10) | (0x20<<0)), |
||||
.datawiratio0 = ((0<<10) | (0<<0)), |
||||
.datagiratio0 = ((0<<10) | (0<<0)), |
||||
.datafwsratio0 = ((0x90<<10) | (0x90<<0)), |
||||
.datawrsratio0 = ((0x50<<10) | (0x50<<0)), |
||||
.datauserank0delay = 1, |
||||
.datadldiff0 = 0x4, |
||||
}; |
||||
#endif |
||||
|
||||
/*
|
||||
* early system init of muxing and clocks. |
||||
*/ |
||||
void s_init(void) |
||||
{ |
||||
#ifdef CONFIG_SPL_BUILD |
||||
/* WDT1 is already running when the bootloader gets control
|
||||
* Disable it to avoid "random" resets |
||||
*/ |
||||
wdt_disable(); |
||||
|
||||
/* Setup the PLLs and the clocks for the peripherals */ |
||||
pll_init(); |
||||
|
||||
/* Enable RTC32K clock */ |
||||
rtc32k_enable(); |
||||
|
||||
/* Set UART pins */ |
||||
enable_uart0_pin_mux(); |
||||
|
||||
/* Set MMC pins */ |
||||
enable_mmc1_pin_mux(); |
||||
|
||||
/* Enable UART */ |
||||
uart_enable(); |
||||
|
||||
gd = &gdata; |
||||
|
||||
preloader_console_init(); |
||||
|
||||
config_dmm(&evm_lisa_map_regs); |
||||
|
||||
config_ddr(0, 0, &evm_ddr2_data, &evm_ddr2_cctrl_data, |
||||
&evm_ddr2_emif0_regs, 0); |
||||
config_ddr(0, 0, &evm_ddr2_data, &evm_ddr2_cctrl_data, |
||||
&evm_ddr2_emif1_regs, 1); |
||||
#endif |
||||
} |
||||
|
||||
/*
|
||||
* Basic board specific setup. Pinmux has been handled already. |
||||
*/ |
||||
int board_init(void) |
||||
{ |
||||
gd->bd->bi_boot_params = PHYS_DRAM_1 + 0x100; |
||||
return 0; |
||||
} |
||||
|
||||
#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_GENERIC_MMC) |
||||
int board_mmc_init(bd_t *bis) |
||||
{ |
||||
omap_mmc_init(1, 0, 0, -1, -1); |
||||
|
||||
return 0; |
||||
} |
||||
#endif |
@ -0,0 +1,7 @@ |
||||
#ifndef _EVM_H |
||||
#define _EVM_H |
||||
|
||||
void enable_uart0_pin_mux(void); |
||||
void enable_mmc1_pin_mux(void); |
||||
|
||||
#endif /* _EVM_H */ |
@ -0,0 +1,51 @@ |
||||
/*
|
||||
* mux.c |
||||
* |
||||
* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as |
||||
* published by the Free Software Foundation version 2. |
||||
* |
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any |
||||
* kind, whether express or implied; without even the implied warranty |
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <asm/arch/sys_proto.h> |
||||
#include <asm/arch/hardware.h> |
||||
#include <asm/arch/mux.h> |
||||
#include <asm/io.h> |
||||
#include <i2c.h> |
||||
#include "evm.h" |
||||
|
||||
static struct module_pin_mux uart0_pin_mux[] = { |
||||
{OFFSET(pincntl70), PULLUP_EN | MODE(0x01)}, /* UART0_RXD */ |
||||
{OFFSET(pincntl71), PULLUP_EN | MODE(0x01)}, /* UART0_TXD */ |
||||
{-1}, |
||||
}; |
||||
|
||||
static struct module_pin_mux mmc1_pin_mux[] = { |
||||
{OFFSET(pincntl1), PULLUP_EN | MODE(0x01)}, /* SD1_CLK */ |
||||
{OFFSET(pincntl2), PULLUP_EN | MODE(0x01)}, /* SD1_CMD */ |
||||
{OFFSET(pincntl3), PULLUP_EN | MODE(0x01)}, /* SD1_DAT[0] */ |
||||
{OFFSET(pincntl4), PULLUP_EN | MODE(0x01)}, /* SD1_DAT[1] */ |
||||
{OFFSET(pincntl5), PULLUP_EN | MODE(0x01)}, /* SD1_DAT[2] */ |
||||
{OFFSET(pincntl6), PULLUP_EN | MODE(0x01)}, /* SD1_DAT[3] */ |
||||
{OFFSET(pincntl74), PULLUP_EN | MODE(0x40)}, /* SD1_POW */ |
||||
{OFFSET(pincntl75), MODE(0x40)}, /* SD1_SDWP */ |
||||
{OFFSET(pincntl80), PULLUP_EN | MODE(0x02)}, /* SD1_SDCD */ |
||||
{-1}, |
||||
}; |
||||
|
||||
void enable_uart0_pin_mux(void) |
||||
{ |
||||
configure_module_pin_mux(uart0_pin_mux); |
||||
} |
||||
|
||||
void enable_mmc1_pin_mux(void) |
||||
{ |
||||
configure_module_pin_mux(mmc1_pin_mux); |
||||
} |
@ -0,0 +1,44 @@ |
||||
Exynos Thermal management Unit |
||||
|
||||
Required properties: |
||||
|
||||
- compatible : Should be "samsung,exynos-tmu" for TMU |
||||
- samsung,min-temp : Minimum temperature value (25 degree celsius) |
||||
- Current temperature of SoC should be more than this value. |
||||
- samsung,max-temp : Maximum temperature value (125 degree celsius) |
||||
- Current temperature of SoC should be less than this value. |
||||
- samsung,start-warning : Temperature at which TMU starts giving warning (degree celsius) |
||||
- samsung,start-tripping : Temperature at which TMU shuts down the system (degree celsius) |
||||
- samsung,hw-tripping : Temperature at which hardware tripping should happen |
||||
in case TMU fails to power off (degree celsius) |
||||
- samsung,efuse-min-value : SOC efuse min value (Constant 40) |
||||
- efuse-value should be more than this value. |
||||
- samsung,efuse-value : SOC actual efuse value (Literal value) |
||||
- This is the data trimming info. |
||||
- This value is used to calculate measuring error. |
||||
- samsung,efuse-max-value : SoC max efuse value (Constant 100) |
||||
- efuse-value should be less than this value. |
||||
- samsung,slope : Default value 274761730 (Constant 0x1060_8802). |
||||
- This is the default value for TMU_CONTROL register. |
||||
- It sets the gain of amplifier to the positive-tc generator block. |
||||
- It selects thermal tripping mode and enables thermal tripping. |
||||
- samsung,dc-value : Measured data calibration value (Constant 25) |
||||
- Used for tempearture calculation. |
||||
- This is 25 because temperature measured is always above 25 degrees. |
||||
|
||||
|
||||
Example: |
||||
|
||||
tmu@10060000 { |
||||
compatible = "samsung,exynos-tmu" |
||||
samsung,min-temp = <25>; |
||||
samsung,max-temp = <125>; |
||||
samsung,start-warning = <95>; |
||||
samsung,start-tripping = <105>; |
||||
samsung,hw-tripping = <110>; |
||||
samsung,efuse-min-value = <40>; |
||||
samsung,efuse-value = <55>; |
||||
samsung,efuse-max-value = <100>; |
||||
samsung,slope = <274761730>; |
||||
samsung,dc-value = <25>; |
||||
}; |
@ -0,0 +1,189 @@ |
||||
/*
|
||||
* This code was extracted from: |
||||
* git://github.com/gonzoua/u-boot-pi.git master
|
||||
* and hence presumably (C) 2012 Oleksandr Tymoshenko |
||||
* |
||||
* Tweaks for U-Boot upstreaming |
||||
* (C) 2012 Stephen Warren |
||||
* |
||||
* Portions (e.g. read/write macros, concepts for back-to-back register write |
||||
* timing workarounds) obviously extracted from the Linux kernel at: |
||||
* https://github.com/raspberrypi/linux.git rpi-3.6.y
|
||||
* |
||||
* The Linux kernel code has the following (c) and license, which is hence |
||||
* propagated to Oleksandr's tree and here: |
||||
* |
||||
* Support for SDHCI device on 2835 |
||||
* Based on sdhci-bcm2708.c (c) 2010 Broadcom |
||||
* |
||||
* 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, write to the Free Software |
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
||||
*/ |
||||
|
||||
/* Supports:
|
||||
* SDHCI platform device - Arasan SD controller in BCM2708 |
||||
* |
||||
* Inspired by sdhci-pci.c, by Pierre Ossman |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <malloc.h> |
||||
#include <sdhci.h> |
||||
|
||||
/* 400KHz is max freq for card ID etc. Use that as min */ |
||||
#define MIN_FREQ 400000 |
||||
|
||||
struct bcm2835_sdhci_host { |
||||
struct sdhci_host host; |
||||
uint twoticks_delay; |
||||
ulong last_write; |
||||
}; |
||||
|
||||
static inline struct bcm2835_sdhci_host *to_bcm(struct sdhci_host *host) |
||||
{ |
||||
return (struct bcm2835_sdhci_host *)host; |
||||
} |
||||
|
||||
static inline void bcm2835_sdhci_raw_writel(struct sdhci_host *host, u32 val, |
||||
int reg) |
||||
{ |
||||
struct bcm2835_sdhci_host *bcm_host = to_bcm(host); |
||||
|
||||
/*
|
||||
* The Arasan has a bugette whereby it may lose the content of |
||||
* successive writes to registers that are within two SD-card clock |
||||
* cycles of each other (a clock domain crossing problem). |
||||
* It seems, however, that the data register does not have this problem. |
||||
* (Which is just as well - otherwise we'd have to nobble the DMA engine |
||||
* too) |
||||
*/ |
||||
while (get_timer(bcm_host->last_write) < bcm_host->twoticks_delay) |
||||
; |
||||
|
||||
writel(val, host->ioaddr + reg); |
||||
bcm_host->last_write = get_timer(0); |
||||
} |
||||
|
||||
static inline u32 bcm2835_sdhci_raw_readl(struct sdhci_host *host, int reg) |
||||
{ |
||||
return readl(host->ioaddr + reg); |
||||
} |
||||
|
||||
static void bcm2835_sdhci_writel(struct sdhci_host *host, u32 val, int reg) |
||||
{ |
||||
bcm2835_sdhci_raw_writel(host, val, reg); |
||||
} |
||||
|
||||
static void bcm2835_sdhci_writew(struct sdhci_host *host, u16 val, int reg) |
||||
{ |
||||
static u32 shadow; |
||||
u32 oldval = (reg == SDHCI_COMMAND) ? shadow : |
||||
bcm2835_sdhci_raw_readl(host, reg & ~3); |
||||
u32 word_num = (reg >> 1) & 1; |
||||
u32 word_shift = word_num * 16; |
||||
u32 mask = 0xffff << word_shift; |
||||
u32 newval = (oldval & ~mask) | (val << word_shift); |
||||
|
||||
if (reg == SDHCI_TRANSFER_MODE) |
||||
shadow = newval; |
||||
else |
||||
bcm2835_sdhci_raw_writel(host, newval, reg & ~3); |
||||
} |
||||
|
||||
static void bcm2835_sdhci_writeb(struct sdhci_host *host, u8 val, int reg) |
||||
{ |
||||
u32 oldval = bcm2835_sdhci_raw_readl(host, reg & ~3); |
||||
u32 byte_num = reg & 3; |
||||
u32 byte_shift = byte_num * 8; |
||||
u32 mask = 0xff << byte_shift; |
||||
u32 newval = (oldval & ~mask) | (val << byte_shift); |
||||
|
||||
bcm2835_sdhci_raw_writel(host, newval, reg & ~3); |
||||
} |
||||
|
||||
static u32 bcm2835_sdhci_readl(struct sdhci_host *host, int reg) |
||||
{ |
||||
u32 val = bcm2835_sdhci_raw_readl(host, reg); |
||||
|
||||
return val; |
||||
} |
||||
|
||||
static u16 bcm2835_sdhci_readw(struct sdhci_host *host, int reg) |
||||
{ |
||||
u32 val = bcm2835_sdhci_raw_readl(host, (reg & ~3)); |
||||
u32 word_num = (reg >> 1) & 1; |
||||
u32 word_shift = word_num * 16; |
||||
u32 word = (val >> word_shift) & 0xffff; |
||||
|
||||
return word; |
||||
} |
||||
|
||||
static u8 bcm2835_sdhci_readb(struct sdhci_host *host, int reg) |
||||
{ |
||||
u32 val = bcm2835_sdhci_raw_readl(host, (reg & ~3)); |
||||
u32 byte_num = reg & 3; |
||||
u32 byte_shift = byte_num * 8; |
||||
u32 byte = (val >> byte_shift) & 0xff; |
||||
|
||||
return byte; |
||||
} |
||||
|
||||
static const struct sdhci_ops bcm2835_ops = { |
||||
.write_l = bcm2835_sdhci_writel, |
||||
.write_w = bcm2835_sdhci_writew, |
||||
.write_b = bcm2835_sdhci_writeb, |
||||
.read_l = bcm2835_sdhci_readl, |
||||
.read_w = bcm2835_sdhci_readw, |
||||
.read_b = bcm2835_sdhci_readb, |
||||
}; |
||||
|
||||
int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq) |
||||
{ |
||||
struct bcm2835_sdhci_host *bcm_host; |
||||
struct sdhci_host *host; |
||||
|
||||
bcm_host = malloc(sizeof(*bcm_host)); |
||||
if (!bcm_host) { |
||||
printf("sdhci_host malloc fail!\n"); |
||||
return 1; |
||||
} |
||||
|
||||
/*
|
||||
* See the comments in bcm2835_sdhci_raw_writel(). |
||||
* |
||||
* This should probably be dynamically calculated based on the actual |
||||
* frequency. However, this is the longest we'll have to wait, and |
||||
* doesn't seem to slow access down too much, so the added complexity |
||||
* doesn't seem worth it for now. |
||||
* |
||||
* 1/MIN_FREQ is (max) time per tick of eMMC clock. |
||||
* 2/MIN_FREQ is time for two ticks. |
||||
* Multiply by 1000000 to get uS per two ticks. |
||||
* +1 for hack rounding. |
||||
*/ |
||||
bcm_host->twoticks_delay = ((2 * 1000000) / MIN_FREQ) + 1; |
||||
bcm_host->last_write = 0; |
||||
|
||||
host = &bcm_host->host; |
||||
host->name = "bcm2835_sdhci"; |
||||
host->ioaddr = (void *)regbase; |
||||
host->quirks = SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_BROKEN_R1B | |
||||
SDHCI_QUIRK_WAIT_SEND_CMD; |
||||
host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; |
||||
host->ops = &bcm2835_ops; |
||||
|
||||
host->version = sdhci_readw(host, SDHCI_HOST_VERSION); |
||||
add_sdhci(host, emmc_freq, MIN_FREQ); |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,319 @@ |
||||
/*
|
||||
* Copyright (c) 2012 Samsung Electronics Co., Ltd. |
||||
* http://www.samsung.com
|
||||
* Akshay Saraswat <akshay.s@samsung.com> |
||||
* |
||||
* EXYNOS - Thermal Management Unit |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* 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. |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||
* MA 02111-1307 USA |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <errno.h> |
||||
#include <fdtdec.h> |
||||
#include <tmu.h> |
||||
#include <asm/arch/tmu.h> |
||||
#include <asm/arch/power.h> |
||||
|
||||
#define TRIMINFO_RELOAD 1 |
||||
#define CORE_EN 1 |
||||
#define THERM_TRIP_EN (1 << 12) |
||||
|
||||
#define INTEN_RISE0 1 |
||||
#define INTEN_RISE1 (1 << 4) |
||||
#define INTEN_RISE2 (1 << 8) |
||||
#define INTEN_FALL0 (1 << 16) |
||||
#define INTEN_FALL1 (1 << 20) |
||||
#define INTEN_FALL2 (1 << 24) |
||||
|
||||
#define TRIM_INFO_MASK 0xff |
||||
|
||||
#define INTCLEAR_RISE0 1 |
||||
#define INTCLEAR_RISE1 (1 << 4) |
||||
#define INTCLEAR_RISE2 (1 << 8) |
||||
#define INTCLEAR_FALL0 (1 << 16) |
||||
#define INTCLEAR_FALL1 (1 << 20) |
||||
#define INTCLEAR_FALL2 (1 << 24) |
||||
#define INTCLEARALL (INTCLEAR_RISE0 | INTCLEAR_RISE1 | \ |
||||
INTCLEAR_RISE2 | INTCLEAR_FALL0 | \
|
||||
INTCLEAR_FALL1 | INTCLEAR_FALL2) |
||||
|
||||
/* Tmeperature threshold values for various thermal events */ |
||||
struct temperature_params { |
||||
/* minimum value in temperature code range */ |
||||
unsigned int min_val; |
||||
/* maximum value in temperature code range */ |
||||
unsigned int max_val; |
||||
/* temperature threshold to start warning */ |
||||
unsigned int start_warning; |
||||
/* temperature threshold CPU tripping */ |
||||
unsigned int start_tripping; |
||||
/* temperature threshold for HW tripping */ |
||||
unsigned int hardware_tripping; |
||||
}; |
||||
|
||||
/* Pre-defined values and thresholds for calibration of current temperature */ |
||||
struct tmu_data { |
||||
/* pre-defined temperature thresholds */ |
||||
struct temperature_params ts; |
||||
/* pre-defined efuse range minimum value */ |
||||
unsigned int efuse_min_value; |
||||
/* pre-defined efuse value for temperature calibration */ |
||||
unsigned int efuse_value; |
||||
/* pre-defined efuse range maximum value */ |
||||
unsigned int efuse_max_value; |
||||
/* current temperature sensing slope */ |
||||
unsigned int slope; |
||||
}; |
||||
|
||||
/* TMU device specific details and status */ |
||||
struct tmu_info { |
||||
/* base Address for the TMU */ |
||||
unsigned tmu_base; |
||||
/* pre-defined values for calibration and thresholds */ |
||||
struct tmu_data data; |
||||
/* value required for triminfo_25 calibration */ |
||||
unsigned int te1; |
||||
/* value required for triminfo_85 calibration */ |
||||
unsigned int te2; |
||||
/* Value for measured data calibration */ |
||||
int dc_value; |
||||
/* enum value indicating status of the TMU */ |
||||
int tmu_state; |
||||
}; |
||||
|
||||
/* Global struct tmu_info variable to store init values */ |
||||
static struct tmu_info gbl_info; |
||||
|
||||
/*
|
||||
* Get current temperature code from register, |
||||
* then calculate and calibrate it's value |
||||
* in degree celsius. |
||||
* |
||||
* @return current temperature of the chip as sensed by TMU |
||||
*/ |
||||
static int get_cur_temp(struct tmu_info *info) |
||||
{ |
||||
int cur_temp; |
||||
struct exynos5_tmu_reg *reg = (struct exynos5_tmu_reg *)info->tmu_base; |
||||
|
||||
/*
|
||||
* Temperature code range between min 25 and max 125. |
||||
* May run more than once for first call as initial sensing |
||||
* has not yet happened. |
||||
*/ |
||||
do { |
||||
cur_temp = readl(®->current_temp) & 0xff; |
||||
} while (cur_temp == 0 && info->tmu_state == TMU_STATUS_NORMAL); |
||||
|
||||
/* Calibrate current temperature */ |
||||
cur_temp = cur_temp - info->te1 + info->dc_value; |
||||
|
||||
return cur_temp; |
||||
} |
||||
|
||||
/*
|
||||
* Monitors status of the TMU device and exynos temperature |
||||
* |
||||
* @param temp pointer to the current temperature value |
||||
* @return enum tmu_status_t value, code indicating event to execute |
||||
*/ |
||||
enum tmu_status_t tmu_monitor(int *temp) |
||||
{ |
||||
int cur_temp; |
||||
struct tmu_data *data = &gbl_info.data; |
||||
|
||||
if (gbl_info.tmu_state == TMU_STATUS_INIT) |
||||
return TMU_STATUS_INIT; |
||||
|
||||
/* Read current temperature of the SOC */ |
||||
cur_temp = get_cur_temp(&gbl_info); |
||||
*temp = cur_temp; |
||||
|
||||
/* Temperature code lies between min 25 and max 125 */ |
||||
if (cur_temp >= data->ts.start_tripping && |
||||
cur_temp <= data->ts.max_val) { |
||||
return TMU_STATUS_TRIPPED; |
||||
} else if (cur_temp >= data->ts.start_warning) { |
||||
return TMU_STATUS_WARNING; |
||||
} else if (cur_temp < data->ts.start_warning && |
||||
cur_temp >= data->ts.min_val) { |
||||
return TMU_STATUS_NORMAL; |
||||
} else { |
||||
/* Temperature code does not lie between min 25 and max 125 */ |
||||
gbl_info.tmu_state = TMU_STATUS_INIT; |
||||
debug("EXYNOS_TMU: Thermal reading failed\n"); |
||||
return TMU_STATUS_INIT; |
||||
} |
||||
} |
||||
|
||||
/*
|
||||
* Get TMU specific pre-defined values from FDT |
||||
* |
||||
* @param info pointer to the tmu_info struct |
||||
* @param blob FDT blob |
||||
* @return int value, 0 for success |
||||
*/ |
||||
static int get_tmu_fdt_values(struct tmu_info *info, const void *blob) |
||||
{ |
||||
#ifdef CONFIG_OF_CONTROL |
||||
int node; |
||||
int error = 0; |
||||
|
||||
/* Get the node from FDT for TMU */ |
||||
node = fdtdec_next_compatible(blob, 0, |
||||
COMPAT_SAMSUNG_EXYNOS_TMU); |
||||
if (node < 0) { |
||||
debug("EXYNOS_TMU: No node for tmu in device tree\n"); |
||||
return -1; |
||||
} |
||||
|
||||
/*
|
||||
* Get the pre-defined TMU specific values from FDT. |
||||
* All of these are expected to be correct otherwise |
||||
* miscalculation of register values in tmu_setup_parameters |
||||
* may result in misleading current temperature. |
||||
*/ |
||||
info->tmu_base = fdtdec_get_addr(blob, node, "reg"); |
||||
if (info->tmu_base == FDT_ADDR_T_NONE) { |
||||
debug("%s: Missing tmu-base\n", __func__); |
||||
return -1; |
||||
} |
||||
info->data.ts.min_val = fdtdec_get_int(blob, |
||||
node, "samsung,min-temp", -1); |
||||
error |= info->data.ts.min_val; |
||||
info->data.ts.max_val = fdtdec_get_int(blob, |
||||
node, "samsung,max-temp", -1); |
||||
error |= info->data.ts.max_val; |
||||
info->data.ts.start_warning = fdtdec_get_int(blob, |
||||
node, "samsung,start-warning", -1); |
||||
error |= info->data.ts.start_warning; |
||||
info->data.ts.start_tripping = fdtdec_get_int(blob, |
||||
node, "samsung,start-tripping", -1); |
||||
error |= info->data.ts.start_tripping; |
||||
info->data.ts.hardware_tripping = fdtdec_get_int(blob, |
||||
node, "samsung,hw-tripping", -1); |
||||
error |= info->data.ts.hardware_tripping; |
||||
info->data.efuse_min_value = fdtdec_get_int(blob, |
||||
node, "samsung,efuse-min-value", -1); |
||||
error |= info->data.efuse_min_value; |
||||
info->data.efuse_value = fdtdec_get_int(blob, |
||||
node, "samsung,efuse-value", -1); |
||||
error |= info->data.efuse_value; |
||||
info->data.efuse_max_value = fdtdec_get_int(blob, |
||||
node, "samsung,efuse-max-value", -1); |
||||
error |= info->data.efuse_max_value; |
||||
info->data.slope = fdtdec_get_int(blob, |
||||
node, "samsung,slope", -1); |
||||
error |= info->data.slope; |
||||
info->dc_value = fdtdec_get_int(blob, |
||||
node, "samsung,dc-value", -1); |
||||
error |= info->dc_value; |
||||
|
||||
if (error == -1) { |
||||
debug("fail to get tmu node properties\n"); |
||||
return -1; |
||||
} |
||||
#endif |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/*
|
||||
* Calibrate and calculate threshold values and |
||||
* enable interrupt levels |
||||
* |
||||
* @param info pointer to the tmu_info struct |
||||
*/ |
||||
static void tmu_setup_parameters(struct tmu_info *info) |
||||
{ |
||||
unsigned int te_code, con; |
||||
unsigned int warning_code, trip_code, hwtrip_code; |
||||
unsigned int cooling_temp; |
||||
unsigned int rising_value; |
||||
struct tmu_data *data = &info->data; |
||||
struct exynos5_tmu_reg *reg = (struct exynos5_tmu_reg *)info->tmu_base; |
||||
|
||||
/* Must reload for reading efuse value from triminfo register */ |
||||
writel(TRIMINFO_RELOAD, ®->triminfo_control); |
||||
|
||||
/* Get the compensation parameter */ |
||||
te_code = readl(®->triminfo); |
||||
info->te1 = te_code & TRIM_INFO_MASK; |
||||
info->te2 = ((te_code >> 8) & TRIM_INFO_MASK); |
||||
|
||||
if ((data->efuse_min_value > info->te1) || |
||||
(info->te1 > data->efuse_max_value) |
||||
|| (info->te2 != 0)) |
||||
info->te1 = data->efuse_value; |
||||
|
||||
/* Get RISING & FALLING Threshold value */ |
||||
warning_code = data->ts.start_warning |
||||
+ info->te1 - info->dc_value; |
||||
trip_code = data->ts.start_tripping |
||||
+ info->te1 - info->dc_value; |
||||
hwtrip_code = data->ts.hardware_tripping |
||||
+ info->te1 - info->dc_value; |
||||
|
||||
cooling_temp = 0; |
||||
|
||||
rising_value = ((warning_code << 8) | |
||||
(trip_code << 16) | |
||||
(hwtrip_code << 24)); |
||||
|
||||
/* Set interrupt level */ |
||||
writel(rising_value, ®->threshold_temp_rise); |
||||
writel(cooling_temp, ®->threshold_temp_fall); |
||||
|
||||
/*
|
||||
* Init TMU control tuning parameters |
||||
* [28:24] VREF - Voltage reference |
||||
* [15:13] THERM_TRIP_MODE - Tripping mode |
||||
* [12] THERM_TRIP_EN - Thermal tripping enable |
||||
* [11:8] BUF_SLOPE_SEL - Gain of amplifier |
||||
* [6] THERM_TRIP_BY_TQ_EN - Tripping by TQ pin |
||||
*/ |
||||
writel(data->slope, ®->tmu_control); |
||||
|
||||
writel(INTCLEARALL, ®->intclear); |
||||
|
||||
/* TMU core enable */ |
||||
con = readl(®->tmu_control); |
||||
con |= THERM_TRIP_EN | CORE_EN; |
||||
|
||||
writel(con, ®->tmu_control); |
||||
|
||||
/* Enable HW thermal trip */ |
||||
set_hw_thermal_trip(); |
||||
|
||||
/* LEV1 LEV2 interrupt enable */ |
||||
writel(INTEN_RISE1 | INTEN_RISE2, ®->inten); |
||||
} |
||||
|
||||
/*
|
||||
* Initialize TMU device |
||||
* |
||||
* @param blob FDT blob |
||||
* @return int value, 0 for success |
||||
*/ |
||||
int tmu_init(const void *blob) |
||||
{ |
||||
gbl_info.tmu_state = TMU_STATUS_INIT; |
||||
if (get_tmu_fdt_values(&gbl_info, blob) < 0) |
||||
goto ret; |
||||
|
||||
tmu_setup_parameters(&gbl_info); |
||||
gbl_info.tmu_state = TMU_STATUS_NORMAL; |
||||
ret: |
||||
|
||||
return gbl_info.tmu_state; |
||||
} |
@ -0,0 +1,550 @@ |
||||
/*
|
||||
* max98095.c -- MAX98095 ALSA SoC Audio driver |
||||
* |
||||
* Copyright 2011 Maxim Integrated Products |
||||
* |
||||
* Modified for uboot by R. Chandrasekar (rcsekar@samsung.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. |
||||
*/ |
||||
#include <asm/arch/clk.h> |
||||
#include <asm/arch/cpu.h> |
||||
#include <asm/arch/power.h> |
||||
#include <asm/gpio.h> |
||||
#include <asm/io.h> |
||||
#include <common.h> |
||||
#include <div64.h> |
||||
#include <fdtdec.h> |
||||
#include <i2c.h> |
||||
#include <sound.h> |
||||
#include "i2s.h" |
||||
#include "max98095.h" |
||||
|
||||
enum max98095_type { |
||||
MAX98095, |
||||
}; |
||||
|
||||
struct max98095_priv { |
||||
enum max98095_type devtype; |
||||
unsigned int sysclk; |
||||
unsigned int rate; |
||||
unsigned int fmt; |
||||
}; |
||||
|
||||
static struct sound_codec_info g_codec_info; |
||||
struct max98095_priv g_max98095_info; |
||||
unsigned int g_max98095_i2c_dev_addr; |
||||
|
||||
/* Index 0 is reserved. */ |
||||
int rate_table[] = {0, 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, |
||||
88200, 96000}; |
||||
|
||||
/*
|
||||
* Writes value to a device register through i2c |
||||
* |
||||
* @param reg reg number to be write |
||||
* @param data data to be writen to the above registor |
||||
* |
||||
* @return int value 1 for change, 0 for no change or negative error code. |
||||
*/ |
||||
static int max98095_i2c_write(unsigned int reg, unsigned char data) |
||||
{ |
||||
debug("%s: Write Addr : 0x%02X, Data : 0x%02X\n", |
||||
__func__, reg, data); |
||||
return i2c_write(g_max98095_i2c_dev_addr, reg, 1, &data, 1); |
||||
} |
||||
|
||||
/*
|
||||
* Read a value from a device register through i2c |
||||
* |
||||
* @param reg reg number to be read |
||||
* @param data address of read data to be stored |
||||
* |
||||
* @return int value 0 for success, -1 in case of error. |
||||
*/ |
||||
static unsigned int max98095_i2c_read(unsigned int reg, unsigned char *data) |
||||
{ |
||||
int ret; |
||||
|
||||
ret = i2c_read(g_max98095_i2c_dev_addr, reg, 1, data, 1); |
||||
if (ret != 0) { |
||||
debug("%s: Error while reading register %#04x\n", |
||||
__func__, reg); |
||||
return -1; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/*
|
||||
* update device register bits through i2c |
||||
* |
||||
* @param reg codec register |
||||
* @param mask register mask |
||||
* @param value new value |
||||
* |
||||
* @return int value 0 for success, non-zero error code. |
||||
*/ |
||||
static int max98095_update_bits(unsigned int reg, unsigned char mask, |
||||
unsigned char value) |
||||
{ |
||||
int change, ret = 0; |
||||
unsigned char old, new; |
||||
|
||||
if (max98095_i2c_read(reg, &old) != 0) |
||||
return -1; |
||||
new = (old & ~mask) | (value & mask); |
||||
change = (old != new) ? 1 : 0; |
||||
if (change) |
||||
ret = max98095_i2c_write(reg, new); |
||||
if (ret < 0) |
||||
return ret; |
||||
|
||||
return change; |
||||
} |
||||
|
||||
/*
|
||||
* codec mclk clock divider coefficients based on sampling rate |
||||
* |
||||
* @param rate sampling rate |
||||
* @param value address of indexvalue to be stored |
||||
* |
||||
* @return 0 for success or negative error code. |
||||
*/ |
||||
static int rate_value(int rate, u8 *value) |
||||
{ |
||||
int i; |
||||
|
||||
for (i = 1; i < ARRAY_SIZE(rate_table); i++) { |
||||
if (rate_table[i] >= rate) { |
||||
*value = i; |
||||
return 0; |
||||
} |
||||
} |
||||
*value = 1; |
||||
|
||||
return -1; |
||||
} |
||||
|
||||
/*
|
||||
* Sets hw params for max98095 |
||||
* |
||||
* @param max98095 max98095 information pointer |
||||
* @param rate Sampling rate |
||||
* @param bits_per_sample Bits per sample |
||||
* |
||||
* @return -1 for error and 0 Success. |
||||
*/ |
||||
static int max98095_hw_params(struct max98095_priv *max98095, |
||||
unsigned int rate, unsigned int bits_per_sample) |
||||
{ |
||||
u8 regval; |
||||
int error; |
||||
|
||||
switch (bits_per_sample) { |
||||
case 16: |
||||
error = max98095_update_bits(M98095_034_DAI2_FORMAT, |
||||
M98095_DAI_WS, 0); |
||||
break; |
||||
case 24: |
||||
error = max98095_update_bits(M98095_034_DAI2_FORMAT, |
||||
M98095_DAI_WS, M98095_DAI_WS); |
||||
break; |
||||
default: |
||||
debug("%s: Illegal bits per sample %d.\n", |
||||
__func__, bits_per_sample); |
||||
return -1; |
||||
} |
||||
|
||||
if (rate_value(rate, ®val)) { |
||||
debug("%s: Failed to set sample rate to %d.\n", |
||||
__func__, rate); |
||||
return -1; |
||||
} |
||||
max98095->rate = rate; |
||||
|
||||
error |= max98095_update_bits(M98095_031_DAI2_CLKMODE, |
||||
M98095_CLKMODE_MASK, regval); |
||||
|
||||
/* Update sample rate mode */ |
||||
if (rate < 50000) |
||||
error |= max98095_update_bits(M98095_038_DAI2_FILTERS, |
||||
M98095_DAI_DHF, 0); |
||||
else |
||||
error |= max98095_update_bits(M98095_038_DAI2_FILTERS, |
||||
M98095_DAI_DHF, M98095_DAI_DHF); |
||||
|
||||
if (error < 0) { |
||||
debug("%s: Error setting hardware params.\n", __func__); |
||||
return -1; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/*
|
||||
* Configures Audio interface system clock for the given frequency |
||||
* |
||||
* @param max98095 max98095 information |
||||
* @param freq Sampling frequency in Hz |
||||
* |
||||
* @return -1 for error and 0 success. |
||||
*/ |
||||
static int max98095_set_sysclk(struct max98095_priv *max98095, |
||||
unsigned int freq) |
||||
{ |
||||
int error = 0; |
||||
|
||||
/* Requested clock frequency is already setup */ |
||||
if (freq == max98095->sysclk) |
||||
return 0; |
||||
|
||||
/* Setup clocks for slave mode, and using the PLL
|
||||
* PSCLK = 0x01 (when master clk is 10MHz to 20MHz) |
||||
* 0x02 (when master clk is 20MHz to 40MHz).. |
||||
* 0x03 (when master clk is 40MHz to 60MHz).. |
||||
*/ |
||||
if ((freq >= 10000000) && (freq < 20000000)) { |
||||
error = max98095_i2c_write(M98095_026_SYS_CLK, 0x10); |
||||
} else if ((freq >= 20000000) && (freq < 40000000)) { |
||||
error = max98095_i2c_write(M98095_026_SYS_CLK, 0x20); |
||||
} else if ((freq >= 40000000) && (freq < 60000000)) { |
||||
error = max98095_i2c_write(M98095_026_SYS_CLK, 0x30); |
||||
} else { |
||||
debug("%s: Invalid master clock frequency\n", __func__); |
||||
return -1; |
||||
} |
||||
|
||||
debug("%s: Clock at %uHz\n", __func__, freq); |
||||
|
||||
if (error < 0) |
||||
return -1; |
||||
|
||||
max98095->sysclk = freq; |
||||
return 0; |
||||
} |
||||
|
||||
/*
|
||||
* Sets Max98095 I2S format |
||||
* |
||||
* @param max98095 max98095 information |
||||
* @param fmt i2S format - supports a subset of the options defined |
||||
* in i2s.h. |
||||
* |
||||
* @return -1 for error and 0 Success. |
||||
*/ |
||||
static int max98095_set_fmt(struct max98095_priv *max98095, int fmt) |
||||
{ |
||||
u8 regval = 0; |
||||
int error = 0; |
||||
|
||||
if (fmt == max98095->fmt) |
||||
return 0; |
||||
|
||||
max98095->fmt = fmt; |
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
||||
case SND_SOC_DAIFMT_CBS_CFS: |
||||
/* Slave mode PLL */ |
||||
error |= max98095_i2c_write(M98095_032_DAI2_CLKCFG_HI, |
||||
0x80); |
||||
error |= max98095_i2c_write(M98095_033_DAI2_CLKCFG_LO, |
||||
0x00); |
||||
break; |
||||
case SND_SOC_DAIFMT_CBM_CFM: |
||||
/* Set to master mode */ |
||||
regval |= M98095_DAI_MAS; |
||||
break; |
||||
case SND_SOC_DAIFMT_CBS_CFM: |
||||
case SND_SOC_DAIFMT_CBM_CFS: |
||||
default: |
||||
debug("%s: Clock mode unsupported\n", __func__); |
||||
return -1; |
||||
} |
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
||||
case SND_SOC_DAIFMT_I2S: |
||||
regval |= M98095_DAI_DLY; |
||||
break; |
||||
case SND_SOC_DAIFMT_LEFT_J: |
||||
break; |
||||
default: |
||||
debug("%s: Unrecognized format.\n", __func__); |
||||
return -1; |
||||
} |
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
||||
case SND_SOC_DAIFMT_NB_NF: |
||||
break; |
||||
case SND_SOC_DAIFMT_NB_IF: |
||||
regval |= M98095_DAI_WCI; |
||||
break; |
||||
case SND_SOC_DAIFMT_IB_NF: |
||||
regval |= M98095_DAI_BCI; |
||||
break; |
||||
case SND_SOC_DAIFMT_IB_IF: |
||||
regval |= M98095_DAI_BCI | M98095_DAI_WCI; |
||||
break; |
||||
default: |
||||
debug("%s: Unrecognized inversion settings.\n", __func__); |
||||
return -1; |
||||
} |
||||
|
||||
error |= max98095_update_bits(M98095_034_DAI2_FORMAT, |
||||
M98095_DAI_MAS | M98095_DAI_DLY | M98095_DAI_BCI | |
||||
M98095_DAI_WCI, regval); |
||||
|
||||
error |= max98095_i2c_write(M98095_035_DAI2_CLOCK, |
||||
M98095_DAI_BSEL64); |
||||
|
||||
if (error < 0) { |
||||
debug("%s: Error setting i2s format.\n", __func__); |
||||
return -1; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/*
|
||||
* resets the audio codec |
||||
* |
||||
* @return -1 for error and 0 success. |
||||
*/ |
||||
static int max98095_reset(void) |
||||
{ |
||||
int i, ret; |
||||
|
||||
/*
|
||||
* Gracefully reset the DSP core and the codec hardware in a proper |
||||
* sequence. |
||||
*/ |
||||
ret = max98095_i2c_write(M98095_00F_HOST_CFG, 0); |
||||
if (ret != 0) { |
||||
debug("%s: Failed to reset DSP: %d\n", __func__, ret); |
||||
return ret; |
||||
} |
||||
|
||||
ret = max98095_i2c_write(M98095_097_PWR_SYS, 0); |
||||
if (ret != 0) { |
||||
debug("%s: Failed to reset codec: %d\n", __func__, ret); |
||||
return ret; |
||||
} |
||||
|
||||
/*
|
||||
* Reset to hardware default for registers, as there is not a soft |
||||
* reset hardware control register. |
||||
*/ |
||||
for (i = M98095_010_HOST_INT_CFG; i < M98095_REG_MAX_CACHED; i++) { |
||||
ret = max98095_i2c_write(i, 0); |
||||
if (ret < 0) { |
||||
debug("%s: Failed to reset: %d\n", __func__, ret); |
||||
return ret; |
||||
} |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/*
|
||||
* Intialise max98095 codec device |
||||
* |
||||
* @param max98095 max98095 information |
||||
* |
||||
* @returns -1 for error and 0 Success. |
||||
*/ |
||||
static int max98095_device_init(struct max98095_priv *max98095) |
||||
{ |
||||
unsigned char id; |
||||
int error = 0; |
||||
|
||||
/* reset the codec, the DSP core, and disable all interrupts */ |
||||
error = max98095_reset(); |
||||
if (error != 0) { |
||||
debug("Reset\n"); |
||||
return error; |
||||
} |
||||
|
||||
/* initialize private data */ |
||||
max98095->sysclk = -1U; |
||||
max98095->rate = -1U; |
||||
max98095->fmt = -1U; |
||||
|
||||
error = max98095_i2c_read(M98095_0FF_REV_ID, &id); |
||||
if (error < 0) { |
||||
debug("%s: Failure reading hardware revision: %d\n", |
||||
__func__, id); |
||||
goto err_access; |
||||
} |
||||
debug("%s: Hardware revision: %c\n", __func__, (id - 0x40) + 'A'); |
||||
|
||||
error |= max98095_i2c_write(M98095_097_PWR_SYS, M98095_PWRSV); |
||||
|
||||
/*
|
||||
* initialize registers to hardware default configuring audio |
||||
* interface2 to DAC |
||||
*/ |
||||
error |= max98095_i2c_write(M98095_048_MIX_DAC_LR, |
||||
M98095_DAI2M_TO_DACL|M98095_DAI2M_TO_DACR); |
||||
|
||||
error |= max98095_i2c_write(M98095_092_PWR_EN_OUT, |
||||
M98095_SPK_SPREADSPECTRUM); |
||||
error |= max98095_i2c_write(M98095_045_CFG_DSP, M98095_DSPNORMAL); |
||||
error |= max98095_i2c_write(M98095_04E_CFG_HP, M98095_HPNORMAL); |
||||
|
||||
error |= max98095_i2c_write(M98095_02C_DAI1_IOCFG, |
||||
M98095_S1NORMAL|M98095_SDATA); |
||||
|
||||
error |= max98095_i2c_write(M98095_036_DAI2_IOCFG, |
||||
M98095_S2NORMAL|M98095_SDATA); |
||||
|
||||
error |= max98095_i2c_write(M98095_040_DAI3_IOCFG, |
||||
M98095_S3NORMAL|M98095_SDATA); |
||||
|
||||
/* take the codec out of the shut down */ |
||||
error |= max98095_update_bits(M98095_097_PWR_SYS, M98095_SHDNRUN, |
||||
M98095_SHDNRUN); |
||||
/* route DACL and DACR output to HO and Spekers */ |
||||
error |= max98095_i2c_write(M98095_050_MIX_SPK_LEFT, 0x01); /* DACL */ |
||||
error |= max98095_i2c_write(M98095_051_MIX_SPK_RIGHT, 0x01);/* DACR */ |
||||
error |= max98095_i2c_write(M98095_04C_MIX_HP_LEFT, 0x01); /* DACL */ |
||||
error |= max98095_i2c_write(M98095_04D_MIX_HP_RIGHT, 0x01); /* DACR */ |
||||
|
||||
/* power Enable */ |
||||
error |= max98095_i2c_write(M98095_091_PWR_EN_OUT, 0xF3); |
||||
|
||||
/* set Volume */ |
||||
error |= max98095_i2c_write(M98095_064_LVL_HP_L, 15); |
||||
error |= max98095_i2c_write(M98095_065_LVL_HP_R, 15); |
||||
error |= max98095_i2c_write(M98095_067_LVL_SPK_L, 16); |
||||
error |= max98095_i2c_write(M98095_068_LVL_SPK_R, 16); |
||||
|
||||
/* Enable DAIs */ |
||||
error |= max98095_i2c_write(M98095_093_BIAS_CTRL, 0x30); |
||||
error |= max98095_i2c_write(M98095_096_PWR_DAC_CK, 0x07); |
||||
|
||||
err_access: |
||||
if (error < 0) |
||||
return -1; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int max98095_do_init(struct sound_codec_info *pcodec_info, |
||||
int sampling_rate, int mclk_freq, |
||||
int bits_per_sample) |
||||
{ |
||||
int ret = 0; |
||||
|
||||
/* Enable codec clock */ |
||||
set_xclkout(); |
||||
|
||||
/* shift the device address by 1 for 7 bit addressing */ |
||||
g_max98095_i2c_dev_addr = pcodec_info->i2c_dev_addr >> 1; |
||||
|
||||
if (pcodec_info->codec_type == CODEC_MAX_98095) |
||||
g_max98095_info.devtype = MAX98095; |
||||
else { |
||||
debug("%s: Codec id [%d] not defined\n", __func__, |
||||
pcodec_info->codec_type); |
||||
return -1; |
||||
} |
||||
|
||||
ret = max98095_device_init(&g_max98095_info); |
||||
if (ret < 0) { |
||||
debug("%s: max98095 codec chip init failed\n", __func__); |
||||
return ret; |
||||
} |
||||
|
||||
ret = max98095_set_sysclk(&g_max98095_info, mclk_freq); |
||||
if (ret < 0) { |
||||
debug("%s: max98095 codec set sys clock failed\n", __func__); |
||||
return ret; |
||||
} |
||||
|
||||
ret = max98095_hw_params(&g_max98095_info, sampling_rate, |
||||
bits_per_sample); |
||||
|
||||
if (ret == 0) { |
||||
ret = max98095_set_fmt(&g_max98095_info, |
||||
SND_SOC_DAIFMT_I2S | |
||||
SND_SOC_DAIFMT_NB_NF | |
||||
SND_SOC_DAIFMT_CBS_CFS); |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
static int get_max98095_codec_values(struct sound_codec_info *pcodec_info, |
||||
const void *blob) |
||||
{ |
||||
int error = 0; |
||||
#ifdef CONFIG_OF_CONTROL |
||||
enum fdt_compat_id compat; |
||||
int node; |
||||
int parent; |
||||
|
||||
/* Get the node from FDT for codec */ |
||||
node = fdtdec_next_compatible(blob, 0, COMPAT_MAXIM_98095_CODEC); |
||||
if (node <= 0) { |
||||
debug("EXYNOS_SOUND: No node for codec in device tree\n"); |
||||
debug("node = %d\n", node); |
||||
return -1; |
||||
} |
||||
|
||||
parent = fdt_parent_offset(blob, node); |
||||
if (parent < 0) { |
||||
debug("%s: Cannot find node parent\n", __func__); |
||||
return -1; |
||||
} |
||||
|
||||
compat = fdtdec_lookup(blob, parent); |
||||
switch (compat) { |
||||
case COMPAT_SAMSUNG_S3C2440_I2C: |
||||
pcodec_info->i2c_bus = i2c_get_bus_num_fdt(parent); |
||||
error |= pcodec_info->i2c_bus; |
||||
debug("i2c bus = %d\n", pcodec_info->i2c_bus); |
||||
pcodec_info->i2c_dev_addr = fdtdec_get_int(blob, node, |
||||
"reg", 0); |
||||
error |= pcodec_info->i2c_dev_addr; |
||||
debug("i2c dev addr = %x\n", pcodec_info->i2c_dev_addr); |
||||
break; |
||||
default: |
||||
debug("%s: Unknown compat id %d\n", __func__, compat); |
||||
return -1; |
||||
} |
||||
#else |
||||
pcodec_info->i2c_bus = AUDIO_I2C_BUS; |
||||
pcodec_info->i2c_dev_addr = AUDIO_I2C_REG; |
||||
debug("i2c dev addr = %d\n", pcodec_info->i2c_dev_addr); |
||||
#endif |
||||
pcodec_info->codec_type = CODEC_MAX_98095; |
||||
if (error == -1) { |
||||
debug("fail to get max98095 codec node properties\n"); |
||||
return -1; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/* max98095 Device Initialisation */ |
||||
int max98095_init(const void *blob, int sampling_rate, int mclk_freq, |
||||
int bits_per_sample) |
||||
{ |
||||
int ret; |
||||
int old_bus = i2c_get_bus_num(); |
||||
struct sound_codec_info *pcodec_info = &g_codec_info; |
||||
|
||||
if (get_max98095_codec_values(pcodec_info, blob) < 0) { |
||||
debug("FDT Codec values failed\n"); |
||||
return -1; |
||||
} |
||||
|
||||
i2c_set_bus_num(pcodec_info->i2c_bus); |
||||
ret = max98095_do_init(pcodec_info, sampling_rate, mclk_freq, |
||||
bits_per_sample); |
||||
i2c_set_bus_num(old_bus); |
||||
|
||||
return ret; |
||||
} |
@ -0,0 +1,311 @@ |
||||
/*
|
||||
* max98095.h -- MAX98095 ALSA SoC Audio driver |
||||
* |
||||
* Copyright 2011 Maxim Integrated Products |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#ifndef _MAX98095_H |
||||
#define _MAX98095_H |
||||
|
||||
/*
|
||||
* MAX98095 Registers Definition |
||||
*/ |
||||
|
||||
#define M98095_000_HOST_DATA 0x00 |
||||
#define M98095_001_HOST_INT_STS 0x01 |
||||
#define M98095_002_HOST_RSP_STS 0x02 |
||||
#define M98095_003_HOST_CMD_STS 0x03 |
||||
#define M98095_004_CODEC_STS 0x04 |
||||
#define M98095_005_DAI1_ALC_STS 0x05 |
||||
#define M98095_006_DAI2_ALC_STS 0x06 |
||||
#define M98095_007_JACK_AUTO_STS 0x07 |
||||
#define M98095_008_JACK_MANUAL_STS 0x08 |
||||
#define M98095_009_JACK_VBAT_STS 0x09 |
||||
#define M98095_00A_ACC_ADC_STS 0x0A |
||||
#define M98095_00B_MIC_NG_AGC_STS 0x0B |
||||
#define M98095_00C_SPK_L_VOLT_STS 0x0C |
||||
#define M98095_00D_SPK_R_VOLT_STS 0x0D |
||||
#define M98095_00E_TEMP_SENSOR_STS 0x0E |
||||
#define M98095_00F_HOST_CFG 0x0F |
||||
#define M98095_010_HOST_INT_CFG 0x10 |
||||
#define M98095_011_HOST_INT_EN 0x11 |
||||
#define M98095_012_CODEC_INT_EN 0x12 |
||||
#define M98095_013_JACK_INT_EN 0x13 |
||||
#define M98095_014_JACK_INT_EN 0x14 |
||||
#define M98095_015_DEC 0x15 |
||||
#define M98095_016_RESERVED 0x16 |
||||
#define M98095_017_RESERVED 0x17 |
||||
#define M98095_018_KEYCODE3 0x18 |
||||
#define M98095_019_KEYCODE2 0x19 |
||||
#define M98095_01A_KEYCODE1 0x1A |
||||
#define M98095_01B_KEYCODE0 0x1B |
||||
#define M98095_01C_OEMCODE1 0x1C |
||||
#define M98095_01D_OEMCODE0 0x1D |
||||
#define M98095_01E_XCFG1 0x1E |
||||
#define M98095_01F_XCFG2 0x1F |
||||
#define M98095_020_XCFG3 0x20 |
||||
#define M98095_021_XCFG4 0x21 |
||||
#define M98095_022_XCFG5 0x22 |
||||
#define M98095_023_XCFG6 0x23 |
||||
#define M98095_024_XGPIO 0x24 |
||||
#define M98095_025_XCLKCFG 0x25 |
||||
#define M98095_026_SYS_CLK 0x26 |
||||
#define M98095_027_DAI1_CLKMODE 0x27 |
||||
#define M98095_028_DAI1_CLKCFG_HI 0x28 |
||||
#define M98095_029_DAI1_CLKCFG_LO 0x29 |
||||
#define M98095_02A_DAI1_FORMAT 0x2A |
||||
#define M98095_02B_DAI1_CLOCK 0x2B |
||||
#define M98095_02C_DAI1_IOCFG 0x2C |
||||
#define M98095_02D_DAI1_TDM 0x2D |
||||
#define M98095_02E_DAI1_FILTERS 0x2E |
||||
#define M98095_02F_DAI1_LVL1 0x2F |
||||
#define M98095_030_DAI1_LVL2 0x30 |
||||
#define M98095_031_DAI2_CLKMODE 0x31 |
||||
#define M98095_032_DAI2_CLKCFG_HI 0x32 |
||||
#define M98095_033_DAI2_CLKCFG_LO 0x33 |
||||
#define M98095_034_DAI2_FORMAT 0x34 |
||||
#define M98095_035_DAI2_CLOCK 0x35 |
||||
#define M98095_036_DAI2_IOCFG 0x36 |
||||
#define M98095_037_DAI2_TDM 0x37 |
||||
#define M98095_038_DAI2_FILTERS 0x38 |
||||
#define M98095_039_DAI2_LVL1 0x39 |
||||
#define M98095_03A_DAI2_LVL2 0x3A |
||||
#define M98095_03B_DAI3_CLKMODE 0x3B |
||||
#define M98095_03C_DAI3_CLKCFG_HI 0x3C |
||||
#define M98095_03D_DAI3_CLKCFG_LO 0x3D |
||||
#define M98095_03E_DAI3_FORMAT 0x3E |
||||
#define M98095_03F_DAI3_CLOCK 0x3F |
||||
#define M98095_040_DAI3_IOCFG 0x40 |
||||
#define M98095_041_DAI3_TDM 0x41 |
||||
#define M98095_042_DAI3_FILTERS 0x42 |
||||
#define M98095_043_DAI3_LVL1 0x43 |
||||
#define M98095_044_DAI3_LVL2 0x44 |
||||
#define M98095_045_CFG_DSP 0x45 |
||||
#define M98095_046_DAC_CTRL1 0x46 |
||||
#define M98095_047_DAC_CTRL2 0x47 |
||||
#define M98095_048_MIX_DAC_LR 0x48 |
||||
#define M98095_049_MIX_DAC_M 0x49 |
||||
#define M98095_04A_MIX_ADC_LEFT 0x4A |
||||
#define M98095_04B_MIX_ADC_RIGHT 0x4B |
||||
#define M98095_04C_MIX_HP_LEFT 0x4C |
||||
#define M98095_04D_MIX_HP_RIGHT 0x4D |
||||
#define M98095_04E_CFG_HP 0x4E |
||||
#define M98095_04F_MIX_RCV 0x4F |
||||
#define M98095_050_MIX_SPK_LEFT 0x50 |
||||
#define M98095_051_MIX_SPK_RIGHT 0x51 |
||||
#define M98095_052_MIX_SPK_CFG 0x52 |
||||
#define M98095_053_MIX_LINEOUT1 0x53 |
||||
#define M98095_054_MIX_LINEOUT2 0x54 |
||||
#define M98095_055_MIX_LINEOUT_CFG 0x55 |
||||
#define M98095_056_LVL_SIDETONE_DAI12 0x56 |
||||
#define M98095_057_LVL_SIDETONE_DAI3 0x57 |
||||
#define M98095_058_LVL_DAI1_PLAY 0x58 |
||||
#define M98095_059_LVL_DAI1_EQ 0x59 |
||||
#define M98095_05A_LVL_DAI2_PLAY 0x5A |
||||
#define M98095_05B_LVL_DAI2_EQ 0x5B |
||||
#define M98095_05C_LVL_DAI3_PLAY 0x5C |
||||
#define M98095_05D_LVL_ADC_L 0x5D |
||||
#define M98095_05E_LVL_ADC_R 0x5E |
||||
#define M98095_05F_LVL_MIC1 0x5F |
||||
#define M98095_060_LVL_MIC2 0x60 |
||||
#define M98095_061_LVL_LINEIN 0x61 |
||||
#define M98095_062_LVL_LINEOUT1 0x62 |
||||
#define M98095_063_LVL_LINEOUT2 0x63 |
||||
#define M98095_064_LVL_HP_L 0x64 |
||||
#define M98095_065_LVL_HP_R 0x65 |
||||
#define M98095_066_LVL_RCV 0x66 |
||||
#define M98095_067_LVL_SPK_L 0x67 |
||||
#define M98095_068_LVL_SPK_R 0x68 |
||||
#define M98095_069_MICAGC_CFG 0x69 |
||||
#define M98095_06A_MICAGC_THRESH 0x6A |
||||
#define M98095_06B_SPK_NOISEGATE 0x6B |
||||
#define M98095_06C_DAI1_ALC1_TIME 0x6C |
||||
#define M98095_06D_DAI1_ALC1_COMP 0x6D |
||||
#define M98095_06E_DAI1_ALC1_EXPN 0x6E |
||||
#define M98095_06F_DAI1_ALC1_GAIN 0x6F |
||||
#define M98095_070_DAI1_ALC2_TIME 0x70 |
||||
#define M98095_071_DAI1_ALC2_COMP 0x71 |
||||
#define M98095_072_DAI1_ALC2_EXPN 0x72 |
||||
#define M98095_073_DAI1_ALC2_GAIN 0x73 |
||||
#define M98095_074_DAI1_ALC3_TIME 0x74 |
||||
#define M98095_075_DAI1_ALC3_COMP 0x75 |
||||
#define M98095_076_DAI1_ALC3_EXPN 0x76 |
||||
#define M98095_077_DAI1_ALC3_GAIN 0x77 |
||||
#define M98095_078_DAI2_ALC1_TIME 0x78 |
||||
#define M98095_079_DAI2_ALC1_COMP 0x79 |
||||
#define M98095_07A_DAI2_ALC1_EXPN 0x7A |
||||
#define M98095_07B_DAI2_ALC1_GAIN 0x7B |
||||
#define M98095_07C_DAI2_ALC2_TIME 0x7C |
||||
#define M98095_07D_DAI2_ALC2_COMP 0x7D |
||||
#define M98095_07E_DAI2_ALC2_EXPN 0x7E |
||||
#define M98095_07F_DAI2_ALC2_GAIN 0x7F |
||||
#define M98095_080_DAI2_ALC3_TIME 0x80 |
||||
#define M98095_081_DAI2_ALC3_COMP 0x81 |
||||
#define M98095_082_DAI2_ALC3_EXPN 0x82 |
||||
#define M98095_083_DAI2_ALC3_GAIN 0x83 |
||||
#define M98095_084_HP_NOISE_GATE 0x84 |
||||
#define M98095_085_AUX_ADC 0x85 |
||||
#define M98095_086_CFG_LINE 0x86 |
||||
#define M98095_087_CFG_MIC 0x87 |
||||
#define M98095_088_CFG_LEVEL 0x88 |
||||
#define M98095_089_JACK_DET_AUTO 0x89 |
||||
#define M98095_08A_JACK_DET_MANUAL 0x8A |
||||
#define M98095_08B_JACK_KEYSCAN_DBC 0x8B |
||||
#define M98095_08C_JACK_KEYSCAN_DLY 0x8C |
||||
#define M98095_08D_JACK_KEY_THRESH 0x8D |
||||
#define M98095_08E_JACK_DC_SLEW 0x8E |
||||
#define M98095_08F_JACK_TEST_CFG 0x8F |
||||
#define M98095_090_PWR_EN_IN 0x90 |
||||
#define M98095_091_PWR_EN_OUT 0x91 |
||||
#define M98095_092_PWR_EN_OUT 0x92 |
||||
#define M98095_093_BIAS_CTRL 0x93 |
||||
#define M98095_094_PWR_DAC_21 0x94 |
||||
#define M98095_095_PWR_DAC_03 0x95 |
||||
#define M98095_096_PWR_DAC_CK 0x96 |
||||
#define M98095_097_PWR_SYS 0x97 |
||||
|
||||
#define M98095_0FF_REV_ID 0xFF |
||||
|
||||
#define M98095_REG_CNT (0xFF+1) |
||||
#define M98095_REG_MAX_CACHED 0X97 |
||||
|
||||
/* MAX98095 Registers Bit Fields */ |
||||
|
||||
/* M98095_00F_HOST_CFG */ |
||||
#define M98095_SEG (1<<0) |
||||
#define M98095_XTEN (1<<1) |
||||
#define M98095_MDLLEN (1<<2) |
||||
|
||||
/* M98095_027_DAI1_CLKMODE, M98095_031_DAI2_CLKMODE, M98095_03B_DAI3_CLKMODE */ |
||||
#define M98095_CLKMODE_MASK 0xFF |
||||
|
||||
/* M98095_02A_DAI1_FORMAT, M98095_034_DAI2_FORMAT, M98095_03E_DAI3_FORMAT */ |
||||
#define M98095_DAI_MAS (1<<7) |
||||
#define M98095_DAI_WCI (1<<6) |
||||
#define M98095_DAI_BCI (1<<5) |
||||
#define M98095_DAI_DLY (1<<4) |
||||
#define M98095_DAI_TDM (1<<2) |
||||
#define M98095_DAI_FSW (1<<1) |
||||
#define M98095_DAI_WS (1<<0) |
||||
|
||||
/* M98095_02B_DAI1_CLOCK, M98095_035_DAI2_CLOCK, M98095_03F_DAI3_CLOCK */ |
||||
#define M98095_DAI_BSEL64 (1<<0) |
||||
#define M98095_DAI_DOSR_DIV2 (0<<5) |
||||
#define M98095_DAI_DOSR_DIV4 (1<<5) |
||||
|
||||
/* M98095_02C_DAI1_IOCFG, M98095_036_DAI2_IOCFG, M98095_040_DAI3_IOCFG */ |
||||
#define M98095_S1NORMAL (1<<6) |
||||
#define M98095_S2NORMAL (2<<6) |
||||
#define M98095_S3NORMAL (3<<6) |
||||
#define M98095_SDATA (3<<0) |
||||
|
||||
/* M98095_02E_DAI1_FILTERS, M98095_038_DAI2_FILTERS, M98095_042_DAI3_FILTERS */ |
||||
#define M98095_DAI_DHF (1<<3) |
||||
|
||||
/* M98095_045_DSP_CFG */ |
||||
#define M98095_DSPNORMAL (5<<4) |
||||
|
||||
/* M98095_048_MIX_DAC_LR */ |
||||
#define M98095_DAI1L_TO_DACR (1<<7) |
||||
#define M98095_DAI1R_TO_DACR (1<<6) |
||||
#define M98095_DAI2M_TO_DACR (1<<5) |
||||
#define M98095_DAI1L_TO_DACL (1<<3) |
||||
#define M98095_DAI1R_TO_DACL (1<<2) |
||||
#define M98095_DAI2M_TO_DACL (1<<1) |
||||
#define M98095_DAI3M_TO_DACL (1<<0) |
||||
|
||||
/* M98095_049_MIX_DAC_M */ |
||||
#define M98095_DAI1L_TO_DACM (1<<3) |
||||
#define M98095_DAI1R_TO_DACM (1<<2) |
||||
#define M98095_DAI2M_TO_DACM (1<<1) |
||||
#define M98095_DAI3M_TO_DACM (1<<0) |
||||
|
||||
/* M98095_04E_MIX_HP_CFG */ |
||||
#define M98095_HPNORMAL (3<<4) |
||||
|
||||
/* M98095_05F_LVL_MIC1, M98095_060_LVL_MIC2 */ |
||||
#define M98095_MICPRE_MASK (3<<5) |
||||
#define M98095_MICPRE_SHIFT 5 |
||||
|
||||
/* M98095_064_LVL_HP_L, M98095_065_LVL_HP_R */ |
||||
#define M98095_HP_MUTE (1<<7) |
||||
|
||||
/* M98095_066_LVL_RCV */ |
||||
#define M98095_REC_MUTE (1<<7) |
||||
|
||||
/* M98095_067_LVL_SPK_L, M98095_068_LVL_SPK_R */ |
||||
#define M98095_SP_MUTE (1<<7) |
||||
|
||||
/* M98095_087_CFG_MIC */ |
||||
#define M98095_MICSEL_MASK (3<<0) |
||||
#define M98095_DIGMIC_L (1<<2) |
||||
#define M98095_DIGMIC_R (1<<3) |
||||
#define M98095_DIGMIC2L (1<<4) |
||||
#define M98095_DIGMIC2R (1<<5) |
||||
|
||||
/* M98095_088_CFG_LEVEL */ |
||||
#define M98095_VSEN (1<<6) |
||||
#define M98095_ZDEN (1<<5) |
||||
#define M98095_BQ2EN (1<<3) |
||||
#define M98095_BQ1EN (1<<2) |
||||
#define M98095_EQ2EN (1<<1) |
||||
#define M98095_EQ1EN (1<<0) |
||||
|
||||
/* M98095_090_PWR_EN_IN */ |
||||
#define M98095_INEN (1<<7) |
||||
#define M98095_MB2EN (1<<3) |
||||
#define M98095_MB1EN (1<<2) |
||||
#define M98095_MBEN (3<<2) |
||||
#define M98095_ADREN (1<<1) |
||||
#define M98095_ADLEN (1<<0) |
||||
|
||||
/* M98095_091_PWR_EN_OUT */ |
||||
#define M98095_HPLEN (1<<7) |
||||
#define M98095_HPREN (1<<6) |
||||
#define M98095_SPLEN (1<<5) |
||||
#define M98095_SPREN (1<<4) |
||||
#define M98095_RECEN (1<<3) |
||||
#define M98095_DALEN (1<<1) |
||||
#define M98095_DAREN (1<<0) |
||||
|
||||
/* M98095_092_PWR_EN_OUT */ |
||||
#define M98095_SPK_FIXEDSPECTRUM (0<<4) |
||||
#define M98095_SPK_SPREADSPECTRUM (1<<4) |
||||
|
||||
/* M98095_097_PWR_SYS */ |
||||
#define M98095_SHDNRUN (1<<7) |
||||
#define M98095_PERFMODE (1<<3) |
||||
#define M98095_HPPLYBACK (1<<2) |
||||
#define M98095_PWRSV8K (1<<1) |
||||
#define M98095_PWRSV (1<<0) |
||||
|
||||
#define M98095_COEFS_PER_BAND 5 |
||||
|
||||
/* Equalizer filter coefficients */ |
||||
#define M98095_110_DAI1_EQ_BASE 0x10 |
||||
#define M98095_142_DAI2_EQ_BASE 0x42 |
||||
|
||||
/* Biquad filter coefficients */ |
||||
#define M98095_174_DAI1_BQ_BASE 0x74 |
||||
#define M98095_17E_DAI2_BQ_BASE 0x7E |
||||
|
||||
/* function prototype */ |
||||
|
||||
/*
|
||||
* intialise max98095 sound codec device for the given configuration |
||||
* |
||||
* @param blob FDT node for codec values |
||||
* @param sampling_rate Sampling rate (Hz) |
||||
* @param mclk_freq MCLK Frequency (Hz) |
||||
* @param bits_per_sample bits per Sample (must be 16 or 24) |
||||
* |
||||
* @returns -1 for error and 0 Success. |
||||
*/ |
||||
int max98095_init(const void *blob, int sampling_rate, int mclk_freq, |
||||
int bits_per_sample); |
||||
|
||||
#endif |
@ -0,0 +1,186 @@ |
||||
/*
|
||||
* Common fdt based SPI driver front end |
||||
* |
||||
* Copyright (c) 2013 NVIDIA Corporation |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* This software is licensed under the terms of the GNU General Public |
||||
* License version 2, as published by the Free Software Foundation, and |
||||
* may be copied, distributed, and modified under those terms. |
||||
* |
||||
* 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, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||
* MA 02111-1307 USA |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <malloc.h> |
||||
#include <asm/io.h> |
||||
#include <asm/gpio.h> |
||||
#include <asm/arch/clock.h> |
||||
#include <asm/arch-tegra/clk_rst.h> |
||||
#include <asm/arch-tegra20/tegra20_sflash.h> |
||||
#include <asm/arch-tegra20/tegra20_slink.h> |
||||
#include <asm/arch-tegra114/tegra114_spi.h> |
||||
#include <spi.h> |
||||
#include <fdtdec.h> |
||||
|
||||
DECLARE_GLOBAL_DATA_PTR; |
||||
|
||||
struct fdt_spi_driver { |
||||
int compat; |
||||
int max_ctrls; |
||||
int (*init)(int *node_list, int count); |
||||
int (*claim_bus)(struct spi_slave *slave); |
||||
int (*release_bus)(struct spi_slave *slave); |
||||
int (*cs_is_valid)(unsigned int bus, unsigned int cs); |
||||
struct spi_slave *(*setup_slave)(unsigned int bus, unsigned int cs, |
||||
unsigned int max_hz, unsigned int mode); |
||||
void (*free_slave)(struct spi_slave *slave); |
||||
void (*cs_activate)(struct spi_slave *slave); |
||||
void (*cs_deactivate)(struct spi_slave *slave); |
||||
int (*xfer)(struct spi_slave *slave, unsigned int bitlen, |
||||
const void *data_out, void *data_in, unsigned long flags); |
||||
}; |
||||
|
||||
static struct fdt_spi_driver fdt_spi_drivers[] = { |
||||
#ifdef CONFIG_TEGRA20_SFLASH |
||||
{ |
||||
.compat = COMPAT_NVIDIA_TEGRA20_SFLASH, |
||||
.max_ctrls = 1, |
||||
.init = tegra20_spi_init, |
||||
.claim_bus = tegra20_spi_claim_bus, |
||||
.cs_is_valid = tegra20_spi_cs_is_valid, |
||||
.setup_slave = tegra20_spi_setup_slave, |
||||
.free_slave = tegra20_spi_free_slave, |
||||
.cs_activate = tegra20_spi_cs_activate, |
||||
.cs_deactivate = tegra20_spi_cs_deactivate, |
||||
.xfer = tegra20_spi_xfer, |
||||
}, |
||||
#endif |
||||
#ifdef CONFIG_TEGRA20_SLINK |
||||
{ |
||||
.compat = COMPAT_NVIDIA_TEGRA20_SLINK, |
||||
.max_ctrls = CONFIG_TEGRA_SLINK_CTRLS, |
||||
.init = tegra30_spi_init, |
||||
.claim_bus = tegra30_spi_claim_bus, |
||||
.cs_is_valid = tegra30_spi_cs_is_valid, |
||||
.setup_slave = tegra30_spi_setup_slave, |
||||
.free_slave = tegra30_spi_free_slave, |
||||
.cs_activate = tegra30_spi_cs_activate, |
||||
.cs_deactivate = tegra30_spi_cs_deactivate, |
||||
.xfer = tegra30_spi_xfer, |
||||
}, |
||||
#endif |
||||
#ifdef CONFIG_TEGRA114_SPI |
||||
{ |
||||
.compat = COMPAT_NVIDIA_TEGRA114_SPI, |
||||
.max_ctrls = CONFIG_TEGRA114_SPI_CTRLS, |
||||
.init = tegra114_spi_init, |
||||
.claim_bus = tegra114_spi_claim_bus, |
||||
.cs_is_valid = tegra114_spi_cs_is_valid, |
||||
.setup_slave = tegra114_spi_setup_slave, |
||||
.free_slave = tegra114_spi_free_slave, |
||||
.cs_activate = tegra114_spi_cs_activate, |
||||
.cs_deactivate = tegra114_spi_cs_deactivate, |
||||
.xfer = tegra114_spi_xfer, |
||||
}, |
||||
#endif |
||||
}; |
||||
|
||||
static struct fdt_spi_driver *driver; |
||||
|
||||
int spi_cs_is_valid(unsigned int bus, unsigned int cs) |
||||
{ |
||||
if (!driver) |
||||
return 0; |
||||
else if (!driver->cs_is_valid) |
||||
return 1; |
||||
else |
||||
return driver->cs_is_valid(bus, cs); |
||||
} |
||||
|
||||
struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, |
||||
unsigned int max_hz, unsigned int mode) |
||||
{ |
||||
if (!driver || !driver->setup_slave) |
||||
return NULL; |
||||
|
||||
return driver->setup_slave(bus, cs, max_hz, mode); |
||||
} |
||||
|
||||
void spi_free_slave(struct spi_slave *slave) |
||||
{ |
||||
if (driver && driver->free_slave) |
||||
return driver->free_slave(slave); |
||||
} |
||||
|
||||
static int spi_init_driver(struct fdt_spi_driver *driver) |
||||
{ |
||||
int count; |
||||
int node_list[driver->max_ctrls]; |
||||
|
||||
count = fdtdec_find_aliases_for_id(gd->fdt_blob, "spi", |
||||
driver->compat, |
||||
node_list, |
||||
driver->max_ctrls); |
||||
return driver->init(node_list, count); |
||||
} |
||||
|
||||
void spi_init(void) |
||||
{ |
||||
int i; |
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fdt_spi_drivers); i++) { |
||||
driver = &fdt_spi_drivers[i]; |
||||
if (!spi_init_driver(driver)) |
||||
break; |
||||
} |
||||
if (i == ARRAY_SIZE(fdt_spi_drivers)) |
||||
driver = NULL; |
||||
} |
||||
|
||||
int spi_claim_bus(struct spi_slave *slave) |
||||
{ |
||||
if (!driver) |
||||
return 1; |
||||
if (!driver->claim_bus) |
||||
return 0; |
||||
|
||||
return driver->claim_bus(slave); |
||||
} |
||||
|
||||
void spi_release_bus(struct spi_slave *slave) |
||||
{ |
||||
if (driver && driver->release_bus) |
||||
driver->release_bus(slave); |
||||
} |
||||
|
||||
void spi_cs_activate(struct spi_slave *slave) |
||||
{ |
||||
if (driver && driver->cs_activate) |
||||
driver->cs_activate(slave); |
||||
} |
||||
|
||||
void spi_cs_deactivate(struct spi_slave *slave) |
||||
{ |
||||
if (driver && driver->cs_deactivate) |
||||
driver->cs_deactivate(slave); |
||||
} |
||||
|
||||
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, |
||||
const void *data_out, void *data_in, unsigned long flags) |
||||
{ |
||||
if (!driver || !driver->xfer) |
||||
return -1; |
||||
|
||||
return driver->xfer(slave, bitlen, data_out, data_in, flags); |
||||
} |
@ -0,0 +1,405 @@ |
||||
/*
|
||||
* NVIDIA Tegra SPI controller (T114 and later) |
||||
* |
||||
* Copyright (c) 2010-2013 NVIDIA Corporation |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* This software is licensed under the terms of the GNU General Public |
||||
* License version 2, as published by the Free Software Foundation, and |
||||
* may be copied, distributed, and modified under those terms. |
||||
* |
||||
* 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, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
||||
* MA 02111-1307 USA |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <malloc.h> |
||||
#include <asm/io.h> |
||||
#include <asm/gpio.h> |
||||
#include <asm/arch/clock.h> |
||||
#include <asm/arch-tegra/clk_rst.h> |
||||
#include <asm/arch-tegra114/tegra114_spi.h> |
||||
#include <spi.h> |
||||
#include <fdtdec.h> |
||||
|
||||
DECLARE_GLOBAL_DATA_PTR; |
||||
|
||||
/* COMMAND1 */ |
||||
#define SPI_CMD1_GO (1 << 31) |
||||
#define SPI_CMD1_M_S (1 << 30) |
||||
#define SPI_CMD1_MODE_MASK 0x3 |
||||
#define SPI_CMD1_MODE_SHIFT 28 |
||||
#define SPI_CMD1_CS_SEL_MASK 0x3 |
||||
#define SPI_CMD1_CS_SEL_SHIFT 26 |
||||
#define SPI_CMD1_CS_POL_INACTIVE3 (1 << 25) |
||||
#define SPI_CMD1_CS_POL_INACTIVE2 (1 << 24) |
||||
#define SPI_CMD1_CS_POL_INACTIVE1 (1 << 23) |
||||
#define SPI_CMD1_CS_POL_INACTIVE0 (1 << 22) |
||||
#define SPI_CMD1_CS_SW_HW (1 << 21) |
||||
#define SPI_CMD1_CS_SW_VAL (1 << 20) |
||||
#define SPI_CMD1_IDLE_SDA_MASK 0x3 |
||||
#define SPI_CMD1_IDLE_SDA_SHIFT 18 |
||||
#define SPI_CMD1_BIDIR (1 << 17) |
||||
#define SPI_CMD1_LSBI_FE (1 << 16) |
||||
#define SPI_CMD1_LSBY_FE (1 << 15) |
||||
#define SPI_CMD1_BOTH_EN_BIT (1 << 14) |
||||
#define SPI_CMD1_BOTH_EN_BYTE (1 << 13) |
||||
#define SPI_CMD1_RX_EN (1 << 12) |
||||
#define SPI_CMD1_TX_EN (1 << 11) |
||||
#define SPI_CMD1_PACKED (1 << 5) |
||||
#define SPI_CMD1_BIT_LEN_MASK 0x1F |
||||
#define SPI_CMD1_BIT_LEN_SHIFT 0 |
||||
|
||||
/* COMMAND2 */ |
||||
#define SPI_CMD2_TX_CLK_TAP_DELAY (1 << 6) |
||||
#define SPI_CMD2_TX_CLK_TAP_DELAY_MASK (0x3F << 6) |
||||
#define SPI_CMD2_RX_CLK_TAP_DELAY (1 << 0) |
||||
#define SPI_CMD2_RX_CLK_TAP_DELAY_MASK (0x3F << 0) |
||||
|
||||
/* TRANSFER STATUS */ |
||||
#define SPI_XFER_STS_RDY (1 << 30) |
||||
|
||||
/* FIFO STATUS */ |
||||
#define SPI_FIFO_STS_CS_INACTIVE (1 << 31) |
||||
#define SPI_FIFO_STS_FRAME_END (1 << 30) |
||||
#define SPI_FIFO_STS_RX_FIFO_FLUSH (1 << 15) |
||||
#define SPI_FIFO_STS_TX_FIFO_FLUSH (1 << 14) |
||||
#define SPI_FIFO_STS_ERR (1 << 8) |
||||
#define SPI_FIFO_STS_TX_FIFO_OVF (1 << 7) |
||||
#define SPI_FIFO_STS_TX_FIFO_UNR (1 << 6) |
||||
#define SPI_FIFO_STS_RX_FIFO_OVF (1 << 5) |
||||
#define SPI_FIFO_STS_RX_FIFO_UNR (1 << 4) |
||||
#define SPI_FIFO_STS_TX_FIFO_FULL (1 << 3) |
||||
#define SPI_FIFO_STS_TX_FIFO_EMPTY (1 << 2) |
||||
#define SPI_FIFO_STS_RX_FIFO_FULL (1 << 1) |
||||
#define SPI_FIFO_STS_RX_FIFO_EMPTY (1 << 0) |
||||
|
||||
#define SPI_TIMEOUT 1000 |
||||
#define TEGRA_SPI_MAX_FREQ 52000000 |
||||
|
||||
struct spi_regs { |
||||
u32 command1; /* 000:SPI_COMMAND1 register */ |
||||
u32 command2; /* 004:SPI_COMMAND2 register */ |
||||
u32 timing1; /* 008:SPI_CS_TIM1 register */ |
||||
u32 timing2; /* 00c:SPI_CS_TIM2 register */ |
||||
u32 xfer_status;/* 010:SPI_TRANS_STATUS register */ |
||||
u32 fifo_status;/* 014:SPI_FIFO_STATUS register */ |
||||
u32 tx_data; /* 018:SPI_TX_DATA register */ |
||||
u32 rx_data; /* 01c:SPI_RX_DATA register */ |
||||
u32 dma_ctl; /* 020:SPI_DMA_CTL register */ |
||||
u32 dma_blk; /* 024:SPI_DMA_BLK register */ |
||||
u32 rsvd[56]; /* 028-107 reserved */ |
||||
u32 tx_fifo; /* 108:SPI_FIFO1 register */ |
||||
u32 rsvd2[31]; /* 10c-187 reserved */ |
||||
u32 rx_fifo; /* 188:SPI_FIFO2 register */ |
||||
u32 spare_ctl; /* 18c:SPI_SPARE_CTRL register */ |
||||
}; |
||||
|
||||
struct tegra_spi_ctrl { |
||||
struct spi_regs *regs; |
||||
unsigned int freq; |
||||
unsigned int mode; |
||||
int periph_id; |
||||
int valid; |
||||
}; |
||||
|
||||
struct tegra_spi_slave { |
||||
struct spi_slave slave; |
||||
struct tegra_spi_ctrl *ctrl; |
||||
}; |
||||
|
||||
static struct tegra_spi_ctrl spi_ctrls[CONFIG_TEGRA114_SPI_CTRLS]; |
||||
|
||||
static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave) |
||||
{ |
||||
return container_of(slave, struct tegra_spi_slave, slave); |
||||
} |
||||
|
||||
int tegra114_spi_cs_is_valid(unsigned int bus, unsigned int cs) |
||||
{ |
||||
if (bus >= CONFIG_TEGRA114_SPI_CTRLS || cs > 3 || !spi_ctrls[bus].valid) |
||||
return 0; |
||||
else |
||||
return 1; |
||||
} |
||||
|
||||
struct spi_slave *tegra114_spi_setup_slave(unsigned int bus, unsigned int cs, |
||||
unsigned int max_hz, unsigned int mode) |
||||
{ |
||||
struct tegra_spi_slave *spi; |
||||
|
||||
debug("%s: bus: %u, cs: %u, max_hz: %u, mode: %u\n", __func__, |
||||
bus, cs, max_hz, mode); |
||||
|
||||
if (!spi_cs_is_valid(bus, cs)) { |
||||
printf("SPI error: unsupported bus %d / chip select %d\n", |
||||
bus, cs); |
||||
return NULL; |
||||
} |
||||
|
||||
if (max_hz > TEGRA_SPI_MAX_FREQ) { |
||||
printf("SPI error: unsupported frequency %d Hz. Max frequency" |
||||
" is %d Hz\n", max_hz, TEGRA_SPI_MAX_FREQ); |
||||
return NULL; |
||||
} |
||||
|
||||
spi = malloc(sizeof(struct tegra_spi_slave)); |
||||
if (!spi) { |
||||
printf("SPI error: malloc of SPI structure failed\n"); |
||||
return NULL; |
||||
} |
||||
spi->slave.bus = bus; |
||||
spi->slave.cs = cs; |
||||
spi->ctrl = &spi_ctrls[bus]; |
||||
if (!spi->ctrl) { |
||||
printf("SPI error: could not find controller for bus %d\n", |
||||
bus); |
||||
return NULL; |
||||
} |
||||
|
||||
if (max_hz < spi->ctrl->freq) { |
||||
debug("%s: limiting frequency from %u to %u\n", __func__, |
||||
spi->ctrl->freq, max_hz); |
||||
spi->ctrl->freq = max_hz; |
||||
} |
||||
spi->ctrl->mode = mode; |
||||
|
||||
return &spi->slave; |
||||
} |
||||
|
||||
void tegra114_spi_free_slave(struct spi_slave *slave) |
||||
{ |
||||
struct tegra_spi_slave *spi = to_tegra_spi(slave); |
||||
|
||||
free(spi); |
||||
} |
||||
|
||||
int tegra114_spi_init(int *node_list, int count) |
||||
{ |
||||
struct tegra_spi_ctrl *ctrl; |
||||
int i; |
||||
int node = 0; |
||||
int found = 0; |
||||
|
||||
for (i = 0; i < count; i++) { |
||||
ctrl = &spi_ctrls[i]; |
||||
node = node_list[i]; |
||||
|
||||
ctrl->regs = (struct spi_regs *)fdtdec_get_addr(gd->fdt_blob, |
||||
node, "reg"); |
||||
if ((fdt_addr_t)ctrl->regs == FDT_ADDR_T_NONE) { |
||||
debug("%s: no spi register found\n", __func__); |
||||
continue; |
||||
} |
||||
ctrl->freq = fdtdec_get_int(gd->fdt_blob, node, |
||||
"spi-max-frequency", 0); |
||||
if (!ctrl->freq) { |
||||
debug("%s: no spi max frequency found\n", __func__); |
||||
continue; |
||||
} |
||||
|
||||
ctrl->periph_id = clock_decode_periph_id(gd->fdt_blob, node); |
||||
if (ctrl->periph_id == PERIPH_ID_NONE) { |
||||
debug("%s: could not decode periph id\n", __func__); |
||||
continue; |
||||
} |
||||
ctrl->valid = 1; |
||||
found = 1; |
||||
|
||||
debug("%s: found controller at %p, freq = %u, periph_id = %d\n", |
||||
__func__, ctrl->regs, ctrl->freq, ctrl->periph_id); |
||||
} |
||||
|
||||
return !found; |
||||
} |
||||
|
||||
int tegra114_spi_claim_bus(struct spi_slave *slave) |
||||
{ |
||||
struct tegra_spi_slave *spi = to_tegra_spi(slave); |
||||
struct spi_regs *regs = spi->ctrl->regs; |
||||
|
||||
/* Change SPI clock to correct frequency, PLLP_OUT0 source */ |
||||
clock_start_periph_pll(spi->ctrl->periph_id, CLOCK_ID_PERIPH, |
||||
spi->ctrl->freq); |
||||
|
||||
/* Clear stale status here */ |
||||
setbits_le32(®s->fifo_status, |
||||
SPI_FIFO_STS_ERR | |
||||
SPI_FIFO_STS_TX_FIFO_OVF | |
||||
SPI_FIFO_STS_TX_FIFO_UNR | |
||||
SPI_FIFO_STS_RX_FIFO_OVF | |
||||
SPI_FIFO_STS_RX_FIFO_UNR | |
||||
SPI_FIFO_STS_TX_FIFO_FULL | |
||||
SPI_FIFO_STS_TX_FIFO_EMPTY | |
||||
SPI_FIFO_STS_RX_FIFO_FULL | |
||||
SPI_FIFO_STS_RX_FIFO_EMPTY); |
||||
debug("%s: FIFO STATUS = %08x\n", __func__, readl(®s->fifo_status)); |
||||
|
||||
/* Set master mode and sw controlled CS */ |
||||
setbits_le32(®s->command1, SPI_CMD1_M_S | SPI_CMD1_CS_SW_HW | |
||||
(spi->ctrl->mode << SPI_CMD1_MODE_SHIFT)); |
||||
debug("%s: COMMAND1 = %08x\n", __func__, readl(®s->command1)); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
void tegra114_spi_cs_activate(struct spi_slave *slave) |
||||
{ |
||||
struct tegra_spi_slave *spi = to_tegra_spi(slave); |
||||
struct spi_regs *regs = spi->ctrl->regs; |
||||
|
||||
clrbits_le32(®s->command1, SPI_CMD1_CS_SW_VAL); |
||||
} |
||||
|
||||
void tegra114_spi_cs_deactivate(struct spi_slave *slave) |
||||
{ |
||||
struct tegra_spi_slave *spi = to_tegra_spi(slave); |
||||
struct spi_regs *regs = spi->ctrl->regs; |
||||
|
||||
setbits_le32(®s->command1, SPI_CMD1_CS_SW_VAL); |
||||
} |
||||
|
||||
int tegra114_spi_xfer(struct spi_slave *slave, unsigned int bitlen, |
||||
const void *data_out, void *data_in, unsigned long flags) |
||||
{ |
||||
struct tegra_spi_slave *spi = to_tegra_spi(slave); |
||||
struct spi_regs *regs = spi->ctrl->regs; |
||||
u32 reg, tmpdout, tmpdin = 0; |
||||
const u8 *dout = data_out; |
||||
u8 *din = data_in; |
||||
int num_bytes; |
||||
int ret; |
||||
|
||||
debug("%s: slave %u:%u dout %p din %p bitlen %u\n", |
||||
__func__, slave->bus, slave->cs, dout, din, bitlen); |
||||
if (bitlen % 8) |
||||
return -1; |
||||
num_bytes = bitlen / 8; |
||||
|
||||
ret = 0; |
||||
|
||||
/* clear all error status bits */ |
||||
reg = readl(®s->fifo_status); |
||||
writel(reg, ®s->fifo_status); |
||||
|
||||
/* clear ready bit */ |
||||
setbits_le32(®s->xfer_status, SPI_XFER_STS_RDY); |
||||
|
||||
clrsetbits_le32(®s->command1, SPI_CMD1_CS_SW_VAL, |
||||
SPI_CMD1_RX_EN | SPI_CMD1_TX_EN | SPI_CMD1_LSBY_FE | |
||||
(slave->cs << SPI_CMD1_CS_SEL_SHIFT)); |
||||
|
||||
/* set xfer size to 1 block (32 bits) */ |
||||
writel(0, ®s->dma_blk); |
||||
|
||||
if (flags & SPI_XFER_BEGIN) |
||||
spi_cs_activate(slave); |
||||
|
||||
/* handle data in 32-bit chunks */ |
||||
while (num_bytes > 0) { |
||||
int bytes; |
||||
int is_read = 0; |
||||
int tm, i; |
||||
|
||||
tmpdout = 0; |
||||
bytes = (num_bytes > 4) ? 4 : num_bytes; |
||||
|
||||
if (dout != NULL) { |
||||
for (i = 0; i < bytes; ++i) |
||||
tmpdout = (tmpdout << 8) | dout[i]; |
||||
dout += bytes; |
||||
} |
||||
|
||||
num_bytes -= bytes; |
||||
|
||||
clrsetbits_le32(®s->command1, |
||||
SPI_CMD1_BIT_LEN_MASK << SPI_CMD1_BIT_LEN_SHIFT, |
||||
(bytes * 8 - 1) << SPI_CMD1_BIT_LEN_SHIFT); |
||||
writel(tmpdout, ®s->tx_fifo); |
||||
setbits_le32(®s->command1, SPI_CMD1_GO); |
||||
|
||||
/*
|
||||
* Wait for SPI transmit FIFO to empty, or to time out. |
||||
* The RX FIFO status will be read and cleared last |
||||
*/ |
||||
for (tm = 0, is_read = 0; tm < SPI_TIMEOUT; ++tm) { |
||||
u32 fifo_status, xfer_status; |
||||
|
||||
fifo_status = readl(®s->fifo_status); |
||||
|
||||
/* We can exit when we've had both RX and TX activity */ |
||||
if (is_read && |
||||
(fifo_status & SPI_FIFO_STS_TX_FIFO_EMPTY)) |
||||
break; |
||||
|
||||
xfer_status = readl(®s->xfer_status); |
||||
if (!(xfer_status & SPI_XFER_STS_RDY)) |
||||
continue; |
||||
|
||||
if (fifo_status & SPI_FIFO_STS_ERR) { |
||||
debug("%s: got a fifo error: ", __func__); |
||||
if (fifo_status & SPI_FIFO_STS_TX_FIFO_OVF) |
||||
debug("tx FIFO overflow "); |
||||
if (fifo_status & SPI_FIFO_STS_TX_FIFO_UNR) |
||||
debug("tx FIFO underrun "); |
||||
if (fifo_status & SPI_FIFO_STS_RX_FIFO_OVF) |
||||
debug("rx FIFO overflow "); |
||||
if (fifo_status & SPI_FIFO_STS_RX_FIFO_UNR) |
||||
debug("rx FIFO underrun "); |
||||
if (fifo_status & SPI_FIFO_STS_TX_FIFO_FULL) |
||||
debug("tx FIFO full "); |
||||
if (fifo_status & SPI_FIFO_STS_TX_FIFO_EMPTY) |
||||
debug("tx FIFO empty "); |
||||
if (fifo_status & SPI_FIFO_STS_RX_FIFO_FULL) |
||||
debug("rx FIFO full "); |
||||
if (fifo_status & SPI_FIFO_STS_RX_FIFO_EMPTY) |
||||
debug("rx FIFO empty "); |
||||
debug("\n"); |
||||
break; |
||||
} |
||||
|
||||
if (!(fifo_status & SPI_FIFO_STS_RX_FIFO_EMPTY)) { |
||||
tmpdin = readl(®s->rx_fifo); |
||||
is_read = 1; |
||||
|
||||
/* swap bytes read in */ |
||||
if (din != NULL) { |
||||
for (i = bytes - 1; i >= 0; --i) { |
||||
din[i] = tmpdin & 0xff; |
||||
tmpdin >>= 8; |
||||
} |
||||
din += bytes; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (tm >= SPI_TIMEOUT) |
||||
ret = tm; |
||||
|
||||
/* clear ACK RDY, etc. bits */ |
||||
writel(readl(®s->fifo_status), ®s->fifo_status); |
||||
} |
||||
|
||||
if (flags & SPI_XFER_END) |
||||
spi_cs_deactivate(slave); |
||||
|
||||
debug("%s: transfer ended. Value=%08x, fifo_status = %08x\n", |
||||
__func__, tmpdin, readl(®s->fifo_status)); |
||||
|
||||
if (ret) { |
||||
printf("%s: timeout during SPI transfer, tm %d\n", |
||||
__func__, ret); |
||||
return -1; |
||||
} |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,127 @@ |
||||
/*
|
||||
* (C) Copyright 2012 Stephen Warren |
||||
* |
||||
* See file CREDITS for list of people who contributed to this |
||||
* project. |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as |
||||
* published by the Free Software Foundation; either version 2 of |
||||
* the License, or (at your option) any later version. |
||||
* |
||||
* 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. |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <lcd.h> |
||||
#include <asm/arch/mbox.h> |
||||
#include <asm/global_data.h> |
||||
|
||||
DECLARE_GLOBAL_DATA_PTR; |
||||
|
||||
/* Global variables that lcd.c expects to exist */ |
||||
int lcd_line_length; |
||||
int lcd_color_fg; |
||||
int lcd_color_bg; |
||||
void *lcd_base; |
||||
void *lcd_console_address; |
||||
short console_col; |
||||
short console_row; |
||||
vidinfo_t panel_info; |
||||
char lcd_cursor_enabled; |
||||
ushort lcd_cursor_width; |
||||
ushort lcd_cursor_height; |
||||
|
||||
struct msg_query { |
||||
struct bcm2835_mbox_hdr hdr; |
||||
struct bcm2835_mbox_tag_physical_w_h physical_w_h; |
||||
u32 end_tag; |
||||
}; |
||||
|
||||
struct msg_setup { |
||||
struct bcm2835_mbox_hdr hdr; |
||||
struct bcm2835_mbox_tag_physical_w_h physical_w_h; |
||||
struct bcm2835_mbox_tag_virtual_w_h virtual_w_h; |
||||
struct bcm2835_mbox_tag_depth depth; |
||||
struct bcm2835_mbox_tag_pixel_order pixel_order; |
||||
struct bcm2835_mbox_tag_alpha_mode alpha_mode; |
||||
struct bcm2835_mbox_tag_virtual_offset virtual_offset; |
||||
struct bcm2835_mbox_tag_overscan overscan; |
||||
struct bcm2835_mbox_tag_allocate_buffer allocate_buffer; |
||||
u32 end_tag; |
||||
}; |
||||
|
||||
void lcd_ctrl_init(void *lcdbase) |
||||
{ |
||||
ALLOC_ALIGN_BUFFER(struct msg_query, msg_query, 1, 16); |
||||
ALLOC_ALIGN_BUFFER(struct msg_setup, msg_setup, 1, 16); |
||||
int ret; |
||||
u32 w, h; |
||||
|
||||
debug("bcm2835: Query resolution...\n"); |
||||
|
||||
BCM2835_MBOX_INIT_HDR(msg_query); |
||||
BCM2835_MBOX_INIT_TAG_NO_REQ(&msg_query->physical_w_h, |
||||
GET_PHYSICAL_W_H); |
||||
ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_query->hdr); |
||||
if (ret) { |
||||
printf("bcm2835: Could not query display resolution\n"); |
||||
/* FIXME: How to disable the LCD to prevent errors? hang()? */ |
||||
return; |
||||
} |
||||
|
||||
w = msg_query->physical_w_h.body.resp.width; |
||||
h = msg_query->physical_w_h.body.resp.height; |
||||
|
||||
debug("bcm2835: Setting up display for %d x %d\n", w, h); |
||||
|
||||
BCM2835_MBOX_INIT_HDR(msg_setup); |
||||
BCM2835_MBOX_INIT_TAG(&msg_setup->physical_w_h, SET_PHYSICAL_W_H); |
||||
msg_setup->physical_w_h.body.req.width = w; |
||||
msg_setup->physical_w_h.body.req.height = h; |
||||
BCM2835_MBOX_INIT_TAG(&msg_setup->virtual_w_h, SET_VIRTUAL_W_H); |
||||
msg_setup->virtual_w_h.body.req.width = w; |
||||
msg_setup->virtual_w_h.body.req.height = h; |
||||
BCM2835_MBOX_INIT_TAG(&msg_setup->depth, SET_DEPTH); |
||||
msg_setup->depth.body.req.bpp = 16; |
||||
BCM2835_MBOX_INIT_TAG(&msg_setup->pixel_order, SET_PIXEL_ORDER); |
||||
msg_setup->pixel_order.body.req.order = BCM2835_MBOX_PIXEL_ORDER_BGR; |
||||
BCM2835_MBOX_INIT_TAG(&msg_setup->alpha_mode, SET_ALPHA_MODE); |
||||
msg_setup->alpha_mode.body.req.alpha = BCM2835_MBOX_ALPHA_MODE_IGNORED; |
||||
BCM2835_MBOX_INIT_TAG(&msg_setup->virtual_offset, SET_VIRTUAL_OFFSET); |
||||
msg_setup->virtual_offset.body.req.x = 0; |
||||
msg_setup->virtual_offset.body.req.y = 0; |
||||
BCM2835_MBOX_INIT_TAG(&msg_setup->overscan, SET_OVERSCAN); |
||||
msg_setup->overscan.body.req.top = 0; |
||||
msg_setup->overscan.body.req.bottom = 0; |
||||
msg_setup->overscan.body.req.left = 0; |
||||
msg_setup->overscan.body.req.right = 0; |
||||
BCM2835_MBOX_INIT_TAG(&msg_setup->allocate_buffer, ALLOCATE_BUFFER); |
||||
msg_setup->allocate_buffer.body.req.alignment = 0x100; |
||||
|
||||
ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_setup->hdr); |
||||
if (ret) { |
||||
printf("bcm2835: Could not configure display\n"); |
||||
/* FIXME: How to disable the LCD to prevent errors? hang()? */ |
||||
return; |
||||
} |
||||
|
||||
w = msg_setup->physical_w_h.body.resp.width; |
||||
h = msg_setup->physical_w_h.body.resp.height; |
||||
|
||||
debug("bcm2835: Final resolution is %d x %d\n", w, h); |
||||
|
||||
panel_info.vl_col = w; |
||||
panel_info.vl_row = h; |
||||
panel_info.vl_bpix = LCD_COLOR16; |
||||
|
||||
gd->fb_base = msg_setup->allocate_buffer.body.resp.fb_address; |
||||
lcd_base = (void *)gd->fb_base; |
||||
} |
||||
|
||||
void lcd_enable(void) |
||||
{ |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue