提交 f43a861e 编写于 作者: B Bernard Xiong

Merge pull request #547 from weety/tms320dm365

[BSP] Add tms320dm365
# for module compiling
import os
Import('RTT_ROOT')
cwd = str(Dir('#'))
objs = []
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
Return('objs')
import os
import sys
import rtconfig
if os.getenv('RTT_ROOT'):
RTT_ROOT = os.getenv('RTT_ROOT')
else:
RTT_ROOT = os.path.normpath(os.getcwd() + '/../..')
sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
from building import *
TARGET = 'rtthread-dm365.' + rtconfig.TARGET_EXT
env = Environment(tools = ['mingw'],
AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS,
AR = rtconfig.AR, ARFLAGS = '-rc',
LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
Export('RTT_ROOT')
Export('rtconfig')
# prepare building environment
objs = PrepareBuilding(env, RTT_ROOT)
# libc testsuite
objs = objs + SConscript(RTT_ROOT + '/examples/libc/SConscript', variant_dir='build/examples/libc', duplicate=0)
# make a building
DoBuilding(TARGET, objs)
import rtconfig
Import('RTT_ROOT')
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd, str(Dir('#'))]
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
/*
* File : application.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2011-01-13 weety first version
*/
/**
* @addtogroup dm365
*/
/*@{*/
#include <rtthread.h>
//#include <rtdevice.h>
#ifdef RT_USING_DFS
/* dfs init */
#include <dfs_init.h>
/* dfs filesystem:ELM FatFs filesystem init */
#include <dfs_elm.h>
/* dfs Filesystem APIs */
#include <dfs_fs.h>
#ifdef RT_USING_DFS_UFFS
/* dfs filesystem:UFFS filesystem init */
#include <dfs_uffs.h>
#endif
#endif
#if defined(RT_USING_DFS_DEVFS)
#include <devfs.h>
#endif
#ifdef RT_USING_SDIO
#include <drivers/mmcsd_core.h>
#endif
#ifdef RT_USING_LWIP
#include <netif/ethernetif.h>
#endif
#ifdef RT_USING_SPI
#include <spi-davinci.h>
#endif
#ifdef RT_USING_LED
#include "led.h"
#endif
#define RT_INIT_THREAD_STACK_SIZE (2*1024)
#ifdef RT_USING_DFS_ROMFS
#include <dfs_romfs.h>
#endif
void rt_init_thread_entry(void* parameter)
{
platform_init();
/* Filesystem Initialization */
#ifdef RT_USING_DFS
{
/* init the device filesystem */
dfs_init();
#if defined(RT_USING_DFS_ELMFAT)
/* init the elm chan FatFs filesystam*/
elm_init();
#endif
#if defined(RT_USING_DFS_ROMFS)
dfs_romfs_init();
if (dfs_mount(RT_NULL, "/rom", "rom", 0, &romfs_root) == 0)
{
rt_kprintf("ROM File System initialized!\n");
}
else
rt_kprintf("ROM File System initialzation failed!\n");
#endif
#if defined(RT_USING_DFS_DEVFS)
devfs_init();
if (dfs_mount(RT_NULL, "/dev", "devfs", 0, 0) == 0)
rt_kprintf("Device File System initialized!\n");
else
rt_kprintf("Device File System initialzation failed!\n");
#ifdef RT_USING_NEWLIB
/* init libc */
libc_system_init(RT_CONSOLE_DEVICE_NAME);
#endif
#endif
#if defined(RT_USING_DFS_UFFS)
{
/* init the uffs filesystem */
dfs_uffs_init();
/* mount flash device as flash directory */
if(dfs_mount("nand0", "/nand0", "uffs", 0, 0) == 0)
rt_kprintf("UFFS File System initialized!\n");
else
rt_kprintf("UFFS File System initialzation failed!\n");
}
#endif
#ifdef RT_USING_I2C
{
rt_i2c_core_init();
davinci_i2c_init("I2C1");
}
#endif
#ifdef RT_USING_SPI
{
rt_hw_spi_init();
}
#endif
#ifdef RT_USING_SDIO
rt_mmcsd_core_init();
rt_mmcsd_blk_init();
rt_hw_mmcsd_init();
rt_thread_delay(RT_TICK_PER_SECOND*2);
/* mount sd card fat partition 1 as root directory */
if (dfs_mount("sd0", "/", "elm", 0, 0) == 0)
{
rt_kprintf("File System initialized!\n");
}
else
rt_kprintf("File System initialzation failed!%d\n", rt_get_errno());
#endif
}
#endif
#ifdef RT_USING_LWIP
{
/* register ethernetif device */
eth_system_device_init();
rt_hw_davinci_emac_init();
/* init lwip system */
lwip_system_init();
}
#endif
}
void rt_led_thread_entry(void* parameter)
{
while(1)
{
/* light on leds for one second */
rt_thread_delay(100);
/* light off leds for one second */
rt_thread_delay(100);
}
}
int rt_application_init()
{
rt_thread_t init_thread;
#ifdef RT_USING_LED
rt_thread_t led_thread;
#endif
#if (RT_THREAD_PRIORITY_MAX == 32)
init_thread = rt_thread_create("init",
rt_init_thread_entry, RT_NULL,
RT_INIT_THREAD_STACK_SIZE, 8, 20);
#ifdef RT_USING_LED
led_thread = rt_thread_create("led",
rt_led_thread_entry, RT_NULL,
512, 20, 20);
#endif
#else
init_thread = rt_thread_create("init",
rt_init_thread_entry, RT_NULL,
RT_INIT_THREAD_STACK_SIZE, 80, 20);
#ifdef RT_USING_LED
led_thread = rt_thread_create("led",
rt_led_thread_entry, RT_NULL,
512, 200, 20);
#endif
#endif
if (init_thread != RT_NULL)
rt_thread_startup(init_thread);
#ifdef RT_USING_LED
if(led_thread != RT_NULL)
rt_thread_startup(led_thread);
#endif
return 0;
}
/* NFSv3 Initialization */
#if defined(RT_USING_DFS) && defined(RT_USING_LWIP) && defined(RT_USING_DFS_NFS)
#include <dfs_nfs.h>
void nfs_start(void)
{
nfs_init();
if (dfs_mount(RT_NULL, "/nfs", "nfs", 0, RT_NFS_HOST_EXPORT) == 0)
{
rt_kprintf("NFSv3 File System initialized!\n");
}
else
rt_kprintf("NFSv3 File System initialzation failed!\n");
}
#include "finsh.h"
FINSH_FUNCTION_EXPORT(nfs_start, start net filesystem);
#endif
/*@}*/
/*
* File : board.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2010-11-13 weety first version
*/
#include <rtthread.h>
#include <rthw.h>
#include <mmu.h>
#include "board.h"
/**
* @addtogroup dm365
*/
/*@{*/
extern void rt_hw_clock_init(void);
extern void rt_hw_uart_init(void);
static struct mem_desc dm365_mem_desc[] = {
{ 0x80000000, 0x88000000-1, 0x80000000, SECT_RW_CB, 0, SECT_MAPPED }, /* 128M cached SDRAM memory */
{ 0xA0000000, 0xA8000000-1, 0x80000000, SECT_RW_NCNB, 0, SECT_MAPPED }, /* 128M No cached SDRAM memory */
{ 0xFFFF0000, 0xFFFF1000-1, 0x80000000, SECT_TO_PAGE, PAGE_RO_CB, PAGE_MAPPED }, /* isr vector table */
{ 0x01C00000, 0x02000000-1, 0x01C00000, SECT_RW_NCNB, 0, SECT_MAPPED }, /* CFG BUS peripherals */
{ 0x02000000, 0x0A000000-1, 0x02000000, SECT_RW_NCNB, 0, SECT_MAPPED }, /* AEMIF */
};
/**
* This function will handle rtos timer
*/
void rt_timer_handler(int vector, void *param)
{
rt_tick_increase();
}
/**
* This function will init timer0 for system ticks
*/
void rt_hw_timer_init()
{
/* timer0, input clocks 24MHz */
volatile timer_regs_t *regs =
(volatile timer_regs_t*)DAVINCI_TIMER1_BASE;//DAVINCI_TIMER0_BASE;
/*disable timer*/
regs->tcr &= ~(0x3UL << 6);
//TIMMODE 32BIT UNCHAINED MODE
regs->tgcr |=(0x1UL << 2);
/*not in reset timer */
regs->tgcr |= (0x1UL << 0);
//regs->tgcr &= ~(0x1UL << 1);
/* set Period Registers */
regs->prd12 = 24000000/RT_TICK_PER_SECOND;
regs->tim12 = 0;
/* Set enable mode */
regs->tcr |= (0x2UL << 6); //period mode
/* install interrupt handler */
rt_hw_interrupt_install(IRQ_DM365_TINT2, rt_timer_handler,
RT_NULL, "timer1_12");//IRQ_DM365_TINT0_TINT12
rt_hw_interrupt_umask(IRQ_DM365_TINT2);//IRQ_DM365_TINT2
}
/**
* This function will init dm365 board
*/
void rt_hw_board_init()
{
psc_change_state(DAVINCI_DM365_LPSC_TIMER0, 3);
psc_change_state(DAVINCI_DM365_LPSC_TIMER1, 3);
/* initialize the system clock */
//rt_hw_clock_init();
davinci_clk_init();
/* initialize uart */
rt_hw_uart_init();
#ifdef RT_USING_CONSOLE
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif
/* initialize mmu */
rt_hw_mmu_init(dm365_mem_desc, sizeof(dm365_mem_desc)/sizeof(dm365_mem_desc[0]));
/* initialize timer0 */
rt_hw_timer_init();
}
/*@}*/
/*
* File : board.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2011-01-13 weety first version
*/
#ifndef __BOARD_H__
#define __BOARD_H__
#include <dm36x.h>
void rt_hw_board_init(void);
#endif
/*
* File : startup.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2011-01-13 weety first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <dm36x.h>
#ifdef RT_USING_FINSH
#include <finsh.h>
#endif
extern void rt_hw_interrupt_init(void);
extern void rt_hw_board_init(void);
extern void rt_serial_init(void);
extern void rt_system_timer_init(void);
extern void rt_system_scheduler_init(void);
extern void rt_thread_idle_init(void);
extern void rt_hw_cpu_icache_enable(void);
extern void rt_show_version(void);
extern void rt_system_heap_init(void*, void*);
extern void rt_hw_finsh_init(void);
extern void rt_application_init(void);
/**
* @addtogroup dm365
*/
/*@{*/
#if defined(__CC_ARM)
extern int Image$$ER_ZI$$ZI$$Base;
extern int Image$$ER_ZI$$ZI$$Length;
extern int Image$$ER_ZI$$ZI$$Limit;
#elif (defined (__GNUC__))
rt_uint8_t _irq_stack_start[1024];
rt_uint8_t _fiq_stack_start[1024];
rt_uint8_t _undefined_stack_start[512];
rt_uint8_t _abort_stack_start[512];
rt_uint8_t _svc_stack_start[1024] SECTION(".nobss");
extern unsigned char __bss_start;
extern unsigned char __bss_end;
#endif
#ifdef RT_USING_FINSH
extern void finsh_system_init(void);
#endif
/**
* This function will startup RT-Thread RTOS.
*/
void rtthread_startup(void)
{
/* enable cpu cache */
//rt_hw_cpu_icache_enable();
//rt_hw_cpu_dcache_enable();
/* initialize hardware interrupt */
rt_hw_interrupt_init();
/* initialize board */
rt_hw_board_init();
/* show version */
rt_show_version();
/* initialize tick */
rt_system_tick_init();
/* initialize kernel object */
rt_system_object_init();
/* initialize timer system */
rt_system_timer_init();
/* initialize heap memory system */
#ifdef __CC_ARM
rt_system_heap_init((void*)&Image$$ER_ZI$$ZI$$Limit, (void*)0x88000000);
#else
rt_system_heap_init((void*)&__bss_end, (void*)0x88000000);
#endif
#ifdef RT_USING_MODULE
/* initialize module system*/
rt_system_module_init();
#endif
/* initialize scheduler system */
rt_system_scheduler_init();
/* initialize application */
rt_application_init();
#ifdef RT_USING_FINSH
/* initialize finsh */
finsh_system_init();
#ifdef RT_USING_DEVICE
finsh_set_device(RT_CONSOLE_DEVICE_NAME);
#endif
#endif
/* initialize system timer thread */
rt_system_timer_thread_init();
/* initialize idle thread */
rt_thread_idle_init();
/* start scheduler */
rt_system_scheduler_start();
/* never reach here */
return ;
}
int main(void)
{
rt_uint32_t RT_UNUSED level;
/* disable interrupt first */
level = rt_hw_interrupt_disable();
/* startup RT-Thread RTOS */
rtthread_startup();
return 0;
}
/*@}*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x80000000;
. = ALIGN(4);
.text :
{
*(.init)
*(.text)
*(.gnu.linkonce.t*)
/* section information for finsh shell */
. = ALIGN(4);
__fsymtab_start = .;
KEEP(*(FSymTab))
__fsymtab_end = .;
. = ALIGN(4);
__vsymtab_start = .;
KEEP(*(VSymTab))
__vsymtab_end = .;
. = ALIGN(4);
/* section information for modules */
. = ALIGN(4);
__rtmsymtab_start = .;
KEEP(*(RTMSymTab))
__rtmsymtab_end = .;
}
. = ALIGN(4);
.rodata : { *(.rodata) *(.rodata.*) *(.gnu.linkonce.r*) *(.eh_frame) }
. = ALIGN(4);
.ctors :
{
PROVIDE(__ctors_start__ = .);
KEEP(*(SORT(.ctors.*)))
KEEP(*(.ctors))
PROVIDE(__ctors_end__ = .);
}
.dtors :
{
PROVIDE(__dtors_start__ = .);
KEEP(*(SORT(.dtors.*)))
KEEP(*(.dtors))
PROVIDE(__dtors_end__ = .);
}
. = ALIGN(4);
.data :
{
*(.data)
*(.data.*)
*(.gnu.linkonce.d*)
}
. = ALIGN(4);
.nobss : { *(.nobss) }
. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss) }
__bss_end = .;
/* stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_info 0 : { *(.debug_info) }
.debug_line 0 : { *(.debug_line) }
.debug_pubnames 0 : { *(.debug_pubnames) }
.debug_aranges 0 : { *(.debug_aranges) }
_end = .;
}
Import('RTT_ROOT')
from building import *
cwd = GetCurrentDir()
#src_drv = ['']
# The set of source files associated with this SConscript file.
path = [cwd]
src = Split("""
davinci_serial.c
""")
if GetDepend('RT_USING_GPIO'):
src += ['gpio.c']
if GetDepend('RT_USING_I2C'):
src += ['i2c-davinci.c']
if GetDepend('RT_USING_SDIO'):
src += ['mmcsd.c']
if GetDepend('RT_USING_SPI'):
src += ['spi-davinci.c']
if GetDepend('RT_USING_LWIP'):
src += ['davinci_emac.c']
group = DefineGroup('Startup', src, depend = [''], CPPPATH = path)
Return('group')
此差异已折叠。
/*
* File : davinci_emac.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2013-01-30 weety first version
*/
#ifndef _DAVINCI_EMAC_H
#define _DAVINCI_EMAC_H
#include <mii.h>
#ifndef NET_IP_ALIGN
#define NET_IP_ALIGN 2
#endif
enum {
EMAC_VERSION_1, /* DM644x */
EMAC_VERSION_2, /* DM646x */
};
#define __iomem
#define BIT(nr) (1UL << (nr))
/* Configuration items */
#define EMAC_DEF_PASS_CRC (0) /* Do not pass CRC upto frames */
#define EMAC_DEF_QOS_EN (0) /* EMAC proprietary QoS disabled */
#define EMAC_DEF_NO_BUFF_CHAIN (0) /* No buffer chain */
#define EMAC_DEF_MACCTRL_FRAME_EN (0) /* Discard Maccontrol frames */
#define EMAC_DEF_SHORT_FRAME_EN (0) /* Discard short frames */
#define EMAC_DEF_ERROR_FRAME_EN (0) /* Discard error frames */
#define EMAC_DEF_PROM_EN (0) /* Promiscous disabled */
#define EMAC_DEF_PROM_CH (0) /* Promiscous channel is 0 */
#define EMAC_DEF_BCAST_EN (1) /* Broadcast enabled */
#define EMAC_DEF_BCAST_CH (0) /* Broadcast channel is 0 */
#define EMAC_DEF_MCAST_EN (1) /* Multicast enabled */
#define EMAC_DEF_MCAST_CH (0) /* Multicast channel is 0 */
#define EMAC_DEF_TXPRIO_FIXED (1) /* TX Priority is fixed */
#define EMAC_DEF_TXPACING_EN (0) /* TX pacing NOT supported*/
#define EMAC_DEF_BUFFER_OFFSET (0) /* Buffer offset to DMA (future) */
#define EMAC_DEF_MIN_ETHPKTSIZE (60) /* Minimum ethernet pkt size */
#define EMAC_DEF_MAX_FRAME_SIZE (1500 + 14 + 4 + 4)
#define EMAC_DEF_TX_CH (0) /* Default 0th channel */
#define EMAC_DEF_RX_CH (0) /* Default 0th channel */
#define EMAC_DEF_MDIO_TICK_MS (10) /* typically 1 tick=1 ms) */
#define EMAC_DEF_MAX_TX_CH (1) /* Max TX channels configured */
#define EMAC_DEF_MAX_RX_CH (1) /* Max RX channels configured */
#define EMAC_POLL_WEIGHT (64) /* Default NAPI poll weight */
/* Buffer descriptor parameters */
#define EMAC_DEF_TX_MAX_SERVICE (32) /* TX max service BD's */
#define EMAC_DEF_RX_MAX_SERVICE (64) /* should = netdev->weight */
/* EMAC register related defines */
#define EMAC_ALL_MULTI_REG_VALUE (0xFFFFFFFF)
#define EMAC_NUM_MULTICAST_BITS (64)
#define EMAC_TEARDOWN_VALUE (0xFFFFFFFC)
#define EMAC_TX_CONTROL_TX_ENABLE_VAL (0x1)
#define EMAC_RX_CONTROL_RX_ENABLE_VAL (0x1)
#define EMAC_MAC_HOST_ERR_INTMASK_VAL (0x2)
#define EMAC_RX_UNICAST_CLEAR_ALL (0xFF)
#define EMAC_INT_MASK_CLEAR (0xFF)
/* RX MBP register bit positions */
#define EMAC_RXMBP_PASSCRC_MASK BIT(30)
#define EMAC_RXMBP_QOSEN_MASK BIT(29)
#define EMAC_RXMBP_NOCHAIN_MASK BIT(28)
#define EMAC_RXMBP_CMFEN_MASK BIT(24)
#define EMAC_RXMBP_CSFEN_MASK BIT(23)
#define EMAC_RXMBP_CEFEN_MASK BIT(22)
#define EMAC_RXMBP_CAFEN_MASK BIT(21)
#define EMAC_RXMBP_PROMCH_SHIFT (16)
#define EMAC_RXMBP_PROMCH_MASK (0x7 << 16)
#define EMAC_RXMBP_BROADEN_MASK BIT(13)
#define EMAC_RXMBP_BROADCH_SHIFT (8)
#define EMAC_RXMBP_BROADCH_MASK (0x7 << 8)
#define EMAC_RXMBP_MULTIEN_MASK BIT(5)
#define EMAC_RXMBP_MULTICH_SHIFT (0)
#define EMAC_RXMBP_MULTICH_MASK (0x7)
#define EMAC_RXMBP_CHMASK (0x7)
/* EMAC register definitions/bit maps used */
# define EMAC_MBP_RXPROMISC (0x00200000)
# define EMAC_MBP_PROMISCCH(ch) (((ch) & 0x7) << 16)
# define EMAC_MBP_RXBCAST (0x00002000)
# define EMAC_MBP_BCASTCHAN(ch) (((ch) & 0x7) << 8)
# define EMAC_MBP_RXMCAST (0x00000020)
# define EMAC_MBP_MCASTCHAN(ch) ((ch) & 0x7)
/* EMAC mac_control register */
#define EMAC_MACCONTROL_TXPTYPE BIT(9)
#define EMAC_MACCONTROL_TXPACEEN BIT(6)
#define EMAC_MACCONTROL_GMIIEN BIT(5)
#define EMAC_MACCONTROL_GIGABITEN BIT(7)
#define EMAC_MACCONTROL_FULLDUPLEXEN BIT(0)
#define EMAC_MACCONTROL_RMIISPEED_MASK BIT(15)
/* GIGABIT MODE related bits */
#define EMAC_DM646X_MACCONTORL_GIG BIT(7)
#define EMAC_DM646X_MACCONTORL_GIGFORCE BIT(17)
/* EMAC mac_status register */
#define EMAC_MACSTATUS_TXERRCODE_MASK (0xF00000)
#define EMAC_MACSTATUS_TXERRCODE_SHIFT (20)
#define EMAC_MACSTATUS_TXERRCH_MASK (0x7)
#define EMAC_MACSTATUS_TXERRCH_SHIFT (16)
#define EMAC_MACSTATUS_RXERRCODE_MASK (0xF000)
#define EMAC_MACSTATUS_RXERRCODE_SHIFT (12)
#define EMAC_MACSTATUS_RXERRCH_MASK (0x7)
#define EMAC_MACSTATUS_RXERRCH_SHIFT (8)
/* EMAC RX register masks */
#define EMAC_RX_MAX_LEN_MASK (0xFFFF)
#define EMAC_RX_BUFFER_OFFSET_MASK (0xFFFF)
/* MAC_IN_VECTOR (0x180) register bit fields */
#define EMAC_DM644X_MAC_IN_VECTOR_HOST_INT BIT(17)
#define EMAC_DM644X_MAC_IN_VECTOR_STATPEND_INT BIT(16)
#define EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC BIT(8)
#define EMAC_DM644X_MAC_IN_VECTOR_TX_INT_VEC BIT(0)
/** NOTE:: For DM646x the IN_VECTOR has changed */
#define EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC BIT(EMAC_DEF_RX_CH)
#define EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC BIT(16 + EMAC_DEF_TX_CH)
#define EMAC_DM646X_MAC_IN_VECTOR_HOST_INT BIT(26)
#define EMAC_DM646X_MAC_IN_VECTOR_STATPEND_INT BIT(27)
/* CPPI bit positions */
#define EMAC_CPPI_SOP_BIT BIT(31)
#define EMAC_CPPI_EOP_BIT BIT(30)
#define EMAC_CPPI_OWNERSHIP_BIT BIT(29)
#define EMAC_CPPI_EOQ_BIT BIT(28)
#define EMAC_CPPI_TEARDOWN_COMPLETE_BIT BIT(27)
#define EMAC_CPPI_PASS_CRC_BIT BIT(26)
#define EMAC_RX_BD_BUF_SIZE (0xFFFF)
#define EMAC_BD_LENGTH_FOR_CACHE (16) /* only CPPI bytes */
#define EMAC_RX_BD_PKT_LENGTH_MASK (0xFFFF)
/* Max hardware defines */
#define EMAC_MAX_TXRX_CHANNELS (8) /* Max hardware channels */
#define EMAC_DEF_MAX_MULTICAST_ADDRESSES (64) /* Max mcast addr's */
/* EMAC Peripheral Device Register Memory Layout structure */
#define EMAC_TXIDVER 0x0
#define EMAC_TXCONTROL 0x4
#define EMAC_TXTEARDOWN 0x8
#define EMAC_RXIDVER 0x10
#define EMAC_RXCONTROL 0x14
#define EMAC_RXTEARDOWN 0x18
#define EMAC_TXINTSTATRAW 0x80
#define EMAC_TXINTSTATMASKED 0x84
#define EMAC_TXINTMASKSET 0x88
#define EMAC_TXINTMASKCLEAR 0x8C
#define EMAC_MACINVECTOR 0x90
#define EMAC_DM646X_MACEOIVECTOR 0x94
#define EMAC_RXINTSTATRAW 0xA0
#define EMAC_RXINTSTATMASKED 0xA4
#define EMAC_RXINTMASKSET 0xA8
#define EMAC_RXINTMASKCLEAR 0xAC
#define EMAC_MACINTSTATRAW 0xB0
#define EMAC_MACINTSTATMASKED 0xB4
#define EMAC_MACINTMASKSET 0xB8
#define EMAC_MACINTMASKCLEAR 0xBC
#define EMAC_RXMBPENABLE 0x100
#define EMAC_RXUNICASTSET 0x104
#define EMAC_RXUNICASTCLEAR 0x108
#define EMAC_RXMAXLEN 0x10C
#define EMAC_RXBUFFEROFFSET 0x110
#define EMAC_RXFILTERLOWTHRESH 0x114
#define EMAC_MACCONTROL 0x160
#define EMAC_MACSTATUS 0x164
#define EMAC_EMCONTROL 0x168
#define EMAC_FIFOCONTROL 0x16C
#define EMAC_MACCONFIG 0x170
#define EMAC_SOFTRESET 0x174
#define EMAC_MACSRCADDRLO 0x1D0
#define EMAC_MACSRCADDRHI 0x1D4
#define EMAC_MACHASH1 0x1D8
#define EMAC_MACHASH2 0x1DC
#define EMAC_MACADDRLO 0x500
#define EMAC_MACADDRHI 0x504
#define EMAC_MACINDEX 0x508
/* EMAC HDP and Completion registors */
#define EMAC_TXHDP(ch) (0x600 + (ch * 4))
#define EMAC_RXHDP(ch) (0x620 + (ch * 4))
#define EMAC_TXCP(ch) (0x640 + (ch * 4))
#define EMAC_RXCP(ch) (0x660 + (ch * 4))
/* EMAC statistics registers */
#define EMAC_RXGOODFRAMES 0x200
#define EMAC_RXBCASTFRAMES 0x204
#define EMAC_RXMCASTFRAMES 0x208
#define EMAC_RXPAUSEFRAMES 0x20C
#define EMAC_RXCRCERRORS 0x210
#define EMAC_RXALIGNCODEERRORS 0x214
#define EMAC_RXOVERSIZED 0x218
#define EMAC_RXJABBER 0x21C
#define EMAC_RXUNDERSIZED 0x220
#define EMAC_RXFRAGMENTS 0x224
#define EMAC_RXFILTERED 0x228
#define EMAC_RXQOSFILTERED 0x22C
#define EMAC_RXOCTETS 0x230
#define EMAC_TXGOODFRAMES 0x234
#define EMAC_TXBCASTFRAMES 0x238
#define EMAC_TXMCASTFRAMES 0x23C
#define EMAC_TXPAUSEFRAMES 0x240
#define EMAC_TXDEFERRED 0x244
#define EMAC_TXCOLLISION 0x248
#define EMAC_TXSINGLECOLL 0x24C
#define EMAC_TXMULTICOLL 0x250
#define EMAC_TXEXCESSIVECOLL 0x254
#define EMAC_TXLATECOLL 0x258
#define EMAC_TXUNDERRUN 0x25C
#define EMAC_TXCARRIERSENSE 0x260
#define EMAC_TXOCTETS 0x264
#define EMAC_NETOCTETS 0x280
#define EMAC_RXSOFOVERRUNS 0x284
#define EMAC_RXMOFOVERRUNS 0x288
#define EMAC_RXDMAOVERRUNS 0x28C
/* EMAC DM644x control registers */
#define EMAC_CTRL_EWCTL (0x4)
#define EMAC_CTRL_EWINTTCNT (0x8)
/* EMAC MDIO related */
/* Mask & Control defines */
#define MDIO_CONTROL_CLKDIV (0xFF)
#define MDIO_CONTROL_ENABLE BIT(30)
#define MDIO_USERACCESS_GO BIT(31)
#define MDIO_USERACCESS_WRITE BIT(30)
#define MDIO_USERACCESS_READ (0)
#define MDIO_USERACCESS_REGADR (0x1F << 21)
#define MDIO_USERACCESS_PHYADR (0x1F << 16)
#define MDIO_USERACCESS_DATA (0xFFFF)
#define MDIO_USERPHYSEL_LINKSEL BIT(7)
#define MDIO_VER_MODID (0xFFFF << 16)
#define MDIO_VER_REVMAJ (0xFF << 8)
#define MDIO_VER_REVMIN (0xFF)
#define MDIO_USERACCESS(inst) (0x80 + (inst * 8))
#define MDIO_USERPHYSEL(inst) (0x84 + (inst * 8))
#define MDIO_CONTROL (0x04)
/* EMAC DM646X control module registers */
#define EMAC_DM646X_CMRXINTEN (0x14)
#define EMAC_DM646X_CMTXINTEN (0x18)
/* EMAC EOI codes for C0 */
#define EMAC_DM646X_MAC_EOI_C0_RXEN (0x01)
#define EMAC_DM646X_MAC_EOI_C0_TXEN (0x02)
/* EMAC Stats Clear Mask */
#define EMAC_STATS_CLR_MASK (0xFFFFFFFF)
/** net_buf_obj: EMAC network bufferdata structure
*
* EMAC network buffer data structure
*/
struct emac_netbufobj {
void *buf_token;
char *data_ptr;
int length;
};
/** net_pkt_obj: EMAC network packet data structure
*
* EMAC network packet data structure - supports buffer list (for future)
*/
struct emac_netpktobj {
void *pkt_token; /* data token may hold tx/rx chan id */
struct emac_netbufobj *buf_list; /* array of network buffer objects */
int num_bufs;
int pkt_length;
};
/** emac_tx_bd: EMAC TX Buffer descriptor data structure
*
* EMAC TX Buffer descriptor data structure
*/
struct emac_tx_bd {
int h_next;
int buff_ptr;
int off_b_len;
int mode; /* SOP, EOP, ownership, EOQ, teardown,Qstarv, length */
struct emac_tx_bd __iomem *next;
void *buf_token;
};
/** emac_txch: EMAC TX Channel data structure
*
* EMAC TX Channel data structure
*/
struct emac_txch {
/* Config related */
rt_uint32_t num_bd;
rt_uint32_t service_max;
/* CPPI specific */
rt_uint32_t alloc_size;
void __iomem *bd_mem;
struct emac_tx_bd __iomem *bd_pool_head;
struct emac_tx_bd __iomem *active_queue_head;
struct emac_tx_bd __iomem *active_queue_tail;
struct emac_tx_bd __iomem *last_hw_bdprocessed;
rt_uint32_t queue_active;
rt_uint32_t teardown_pending;
rt_uint32_t *tx_complete;
/** statistics */
rt_uint32_t proc_count; /* TX: # of times emac_tx_bdproc is called */
rt_uint32_t mis_queued_packets;
rt_uint32_t queue_reinit;
rt_uint32_t end_of_queue_add;
rt_uint32_t out_of_tx_bd;
rt_uint32_t no_active_pkts; /* IRQ when there were no packets to process */
rt_uint32_t active_queue_count;
};
/** emac_rx_bd: EMAC RX Buffer descriptor data structure
*
* EMAC RX Buffer descriptor data structure
*/
struct emac_rx_bd {
int h_next;
int buff_ptr;
int off_b_len;
int mode;
struct emac_rx_bd __iomem *next;
void *data_ptr;
void *buf_token;
};
/** emac_rxch: EMAC RX Channel data structure
*
* EMAC RX Channel data structure
*/
struct emac_rxch {
/* configuration info */
rt_uint32_t num_bd;
rt_uint32_t service_max;
rt_uint32_t buf_size;
char mac_addr[6];
/** CPPI specific */
rt_uint32_t alloc_size;
void __iomem *bd_mem;
struct emac_rx_bd __iomem *bd_pool_head;
struct emac_rx_bd __iomem *active_queue_head;
struct emac_rx_bd __iomem *active_queue_tail;
rt_uint32_t queue_active;
rt_uint32_t teardown_pending;
/* packet and buffer objects */
struct emac_netpktobj pkt_queue;
struct emac_netbufobj buf_queue;
/** statistics */
rt_uint32_t proc_count; /* number of times emac_rx_bdproc is called */
rt_uint32_t processed_bd;
rt_uint32_t recycled_bd;
rt_uint32_t out_of_rx_bd;
rt_uint32_t out_of_rx_buffers;
rt_uint32_t queue_reinit;
rt_uint32_t end_of_queue_add;
rt_uint32_t end_of_queue;
rt_uint32_t mis_queued_packets;
};
struct net_device_stats
{
unsigned long rx_packets; /* total packets received */
unsigned long tx_packets; /* total packets transmitted */
unsigned long rx_bytes; /* total bytes received */
unsigned long tx_bytes; /* total bytes transmitted */
unsigned long rx_errors; /* bad packets received */
unsigned long tx_errors; /* packet transmit problems */
unsigned long rx_dropped; /* no space in linux buffers */
unsigned long tx_dropped; /* no space available in linux */
unsigned long multicast; /* multicast packets received */
unsigned long collisions;
/* detailed rx_errors: */
unsigned long rx_length_errors;
unsigned long rx_over_errors; /* receiver ring buff overflow */
unsigned long rx_crc_errors; /* recved pkt with crc error */
unsigned long rx_frame_errors; /* recv'd frame alignment error */
unsigned long rx_fifo_errors; /* recv'r fifo overrun */
unsigned long rx_missed_errors; /* receiver missed packet */
/* detailed tx_errors */
unsigned long tx_aborted_errors;
unsigned long tx_carrier_errors;
unsigned long tx_fifo_errors;
unsigned long tx_heartbeat_errors;
unsigned long tx_window_errors;
/* for cslip etc */
unsigned long rx_compressed;
unsigned long tx_compressed;
};
/* emac_priv: EMAC private data structure
*
* EMAC adapter private data structure
*/
#define MAX_ADDR_LEN 6
struct emac_priv {
/* inherit from ethernet device */
struct eth_device parent;
/* interface address info. */
rt_uint8_t mac_addr[MAX_ADDR_LEN]; /* hw address */
unsigned short phy_addr;
struct rt_semaphore tx_lock;
struct rt_semaphore rx_lock;
void __iomem *remap_addr;
rt_uint32_t emac_base_phys;
void __iomem *emac_base;
void __iomem *ctrl_base;
void __iomem *emac_ctrl_ram;
void __iomem *mdio_base;
rt_uint32_t ctrl_ram_size;
rt_uint32_t hw_ram_addr;
struct emac_txch *txch[EMAC_DEF_MAX_TX_CH];
struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH];
rt_uint32_t link; /* 1=link on, 0=link off */
rt_uint32_t speed; /* 0=Auto Neg, 1=No PHY, 10,100, 1000 - mbps */
rt_uint32_t duplex; /* Link duplex: 0=Half, 1=Full */
rt_uint32_t rx_buf_size;
rt_uint32_t isr_count;
rt_uint8_t rmii_en;
rt_uint8_t version;
struct net_device_stats net_dev_stats;
rt_uint32_t mac_hash1;
rt_uint32_t mac_hash2;
rt_uint32_t multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS];
rt_uint32_t rx_addr_type;
/* periodic timer required for MDIO polling */
struct rt_timer timer;
rt_uint32_t periodic_ticks;
rt_uint32_t timer_active;
rt_uint32_t phy_mask;
/* mii_bus,phy members */
struct rt_semaphore lock;
};
#endif /* _DAVINCI_EMAC_H */
/*
* File : davinci_serial.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2011-01-13 weety first version
*/
#include <rtthread.h>
#include <rthw.h>
#include <dm36x.h>
#include <rtdevice.h>
static struct rt_serial_device davinci_serial_dev0;
static struct rt_serial_device davinci_serial_dev1;
#define LSR_DR 0x01 /* Data ready */
#define LSR_THRE 0x20 /* Xmit holding register empty */
//#define USTAT_TXB_EMPTY 0x02 /* tx buffer empty */
#define BPS 115200 /* serial baudrate */
typedef struct uartport
{
volatile rt_uint32_t rbr;
volatile rt_uint32_t ier;
volatile rt_uint32_t fcr;
volatile rt_uint32_t lcr;
volatile rt_uint32_t mcr;
volatile rt_uint32_t lsr;
volatile rt_uint32_t msr;
volatile rt_uint32_t scr;
volatile rt_uint32_t dll;
volatile rt_uint32_t dlh;
volatile rt_uint32_t res[2];
volatile rt_uint32_t pwremu_mgmt;
volatile rt_uint32_t mdr;
}uartport;
#define thr rbr
#define iir fcr
#define UART0 ((struct uartport *)DAVINCI_UART0_BASE)
#define UART1 ((struct uartport *)DM365_UART1_BASE)
/**
* This function will handle serial
*/
void rt_davinci_serial_handler(int vector, void *param)
{
struct rt_serial_device *dev = (struct rt_serial_device *)param;
rt_hw_serial_isr(dev, RT_SERIAL_EVENT_RX_IND);
}
/**
* UART device in RT-Thread
*/
static rt_err_t davinci_uart_configure(struct rt_serial_device *serial,
struct serial_configure *cfg)
{
return RT_EOK;
}
static rt_err_t davinci_uart_control(struct rt_serial_device *serial,
int cmd, void *arg)
{
uartport *uart = serial->parent.user_data;
switch (cmd)
{
case RT_DEVICE_CTRL_CLR_INT:
/* disable rx irq */
if (uart == UART0)
rt_hw_interrupt_mask(IRQ_UARTINT0);
else if (uart == UART1)
rt_hw_interrupt_mask(IRQ_UARTINT1);
break;
case RT_DEVICE_CTRL_SET_INT:
/* enable rx irq */
if (uart == UART0)
rt_hw_interrupt_umask(IRQ_UARTINT0);
else if (uart == UART1)
rt_hw_interrupt_umask(IRQ_UARTINT1);
break;
}
return RT_EOK;
}
static int davinci_uart_putc(struct rt_serial_device *serial, char c)
{
rt_uint32_t level;
uartport *uart = serial->parent.user_data;
while (!(uart->lsr & LSR_THRE));
uart->thr = c;
return 1;
}
static int davinci_uart_getc(struct rt_serial_device *serial)
{
int result;
uartport *uart = serial->parent.user_data;
if (uart->lsr & LSR_DR)
{
result = uart->rbr & 0xff;
}
else
{
result = -1;
}
return result;
}
static const struct rt_uart_ops davinci_uart_ops =
{
davinci_uart_configure,
davinci_uart_control,
davinci_uart_putc,
davinci_uart_getc,
};
void davinci_uart0_init(void)
{
rt_uint32_t divisor;
divisor = (24000000 + (115200 * (16 / 2))) / (16 * 115200);
UART0->ier = 0;
UART0->lcr = 0x83; //8N1
UART0->dll = 0;
UART0->dlh = 0;
UART0->lcr = 0x03;
UART0->mcr = 0x03; //RTS,CTS
UART0->fcr = 0x07; //FIFO
UART0->lcr = 0x83;
UART0->dll = divisor & 0xff;
UART0->dlh = (divisor >> 8) & 0xff;
UART0->lcr = 0x03;
UART0->mdr = 0; //16x over-sampling
UART0->pwremu_mgmt = 0x6000;
rt_hw_interrupt_install(IRQ_UARTINT0, rt_davinci_serial_handler,
(void *)&davinci_serial_dev0, "UART0");
rt_hw_interrupt_mask(IRQ_UARTINT0);
UART0->ier = 0x05;
}
void davinci_uart_gpio_init()
{
rt_uint32_t val;
val = davinci_readl(PINMUX3);
val &= 0xf3ffffff; /* gio23 RS485_CTRL */
val |= 0x60000000; /*UART1_TXD (gio25)*/
davinci_writel(val, PINMUX3);
val = davinci_readl(PINMUX4);
val |= 0x0000c000; /* UART1_RXD (gio34) */
davinci_writel(val, PINMUX4);
val = davinci_readl(DAVINCI_GPIO_BASE + 0x10);
val &= ~(1 << 23);
davinci_writel(val, DAVINCI_GPIO_BASE + 0x10);
davinci_writel((1<<23), DAVINCI_GPIO_BASE + 0x1C);
}
void davinci_uart1_init(void)
{
rt_uint32_t divisor;
rt_uint32_t freq;
rt_uint32_t baudrate;
struct clk *clk;
davinci_uart_gpio_init();
psc_change_state(DAVINCI_DM365_LPSC_UART1, PSC_ENABLE);
clk = clk_get("UART1");
freq = clk_get_rate(clk);
baudrate = 9600;
divisor = (freq + (baudrate * (16 / 2))) / (16 * baudrate);
UART1->ier = 0;
UART1->lcr = 0x87; //8N2, 0x83 8N1
UART1->dll = 0;
UART1->dlh = 0;
UART1->lcr = 0x07;
UART1->mcr = 0x03; //RTS,CTS
UART1->fcr = 0x07; //FIFO
UART1->lcr = 0x87;
UART1->dll = divisor & 0xff;
UART1->dlh = (divisor >> 8) & 0xff;
UART1->lcr = 0x07;
UART1->mdr = 0; //16x over-sampling
UART1->pwremu_mgmt = 0x6000;
rt_hw_interrupt_install(IRQ_UARTINT1, rt_davinci_serial_handler,
(void *)&davinci_serial_dev1, "UART1");
rt_hw_interrupt_mask(IRQ_UARTINT1);
UART1->ier = 0x05;
}
/**
* This function will handle init uart
*/
void rt_hw_uart_init(void)
{
davinci_serial_dev0.ops = &davinci_uart_ops;
//davinci_serial_dev0.config = RT_SERIAL_CONFIG_DEFAULT;
davinci_serial_dev0.config.baud_rate = BAUD_RATE_115200;
davinci_serial_dev0.config.bit_order = BIT_ORDER_LSB;
davinci_serial_dev0.config.data_bits = DATA_BITS_8;
davinci_serial_dev0.config.parity = PARITY_NONE;
davinci_serial_dev0.config.stop_bits = STOP_BITS_1;
davinci_serial_dev0.config.invert = NRZ_NORMAL;
davinci_serial_dev0.config.bufsz = RT_SERIAL_RB_BUFSZ;
/* register vcom device */
rt_hw_serial_register(&davinci_serial_dev0, "uart0",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM,
UART0);
davinci_uart0_init();
davinci_serial_dev1.ops = &davinci_uart_ops;
//davinci_serial_dev1.config = RT_SERIAL_CONFIG_DEFAULT;
davinci_serial_dev1.config.baud_rate = BAUD_RATE_115200;
davinci_serial_dev1.config.bit_order = BIT_ORDER_LSB;
davinci_serial_dev1.config.data_bits = DATA_BITS_8;
davinci_serial_dev1.config.parity = PARITY_NONE;
davinci_serial_dev1.config.stop_bits = STOP_BITS_1;
davinci_serial_dev1.config.invert = NRZ_NORMAL;
davinci_serial_dev1.config.bufsz = RT_SERIAL_RB_BUFSZ;
/* register vcom device */
rt_hw_serial_register(&davinci_serial_dev1, "uart1",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM,
UART1);
davinci_uart1_init();
}
/*
* File : gpio.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2011-01-13 weety first version
*/
#include <rtthread.h>
#include "gpio.h"
#define GPIO0_BASE (DAVINCI_GPIO_BASE + 0x10)
#define GPIO1_BASE (DAVINCI_GPIO_BASE + 0x38)
#define GPIO2_BASE (DAVINCI_GPIO_BASE + 0x60)
#define GPIO3_BASE (DAVINCI_GPIO_BASE + 0x88)
static unsigned int dm365_gpio_base = (unsigned int)GPIO0_BASE;
#define GPIO_OE (dm365_gpio_base + 0x00)
#define GPIO_DATAIN (dm365_gpio_base + 0x10)
#define GPIO_DATAOUT (dm365_gpio_base + 0x04)
#define GPIO_CLROUT (dm365_gpio_base + 0x0C)
#define GPIO_SETOUT (dm365_gpio_base + 0x08)
#define gpio_dirin(n) *(volatile unsigned int *)((GPIO_OE)) |= 1<<(n)
#define gpio_dirout(n) *(volatile unsigned int *)((GPIO_OE)) &= ~(1u<<(n))
#define gpio_set(n) *(volatile unsigned int *)((GPIO_SETOUT)) = 1<<(n)
#define gpio_clr(n) *(volatile unsigned int *)((GPIO_CLROUT)) = 1<<(n)
#define gpio_get(n) ( ( *(volatile unsigned int *)((GPIO_DATAIN)) & (1<<(n)) ) ? 1 : 0 )
#define GPIO_GRP_MASK (5)
static int gpio_to_base(unsigned int gpio)
{
unsigned int grp_idx;
int ret;
grp_idx = gpio >> GPIO_GRP_MASK;
switch (grp_idx) {
case 0:
dm365_gpio_base = (unsigned int)GPIO0_BASE;
ret = 0;
break;
case 1:
dm365_gpio_base = (unsigned int)GPIO1_BASE;
ret = 0;
break;
case 2:
dm365_gpio_base = (unsigned int)GPIO2_BASE;
ret = 0;
break;
case 3:
dm365_gpio_base = (unsigned int)GPIO3_BASE;
ret = 0;
break;
default:
ret =-RT_EIO;
break;
}
return ret;
}
int gpio_direction_input(unsigned int gpio)
{
unsigned int offset;
int ret=0;
rt_ubase_t temp = rt_hw_interrupt_disable();
ret = gpio_to_base(gpio);
if (ret < 0) {
goto gpio_free;
}
offset = gpio & ((1 << GPIO_GRP_MASK) -1);
gpio_dirin(offset);
gpio_free:
rt_hw_interrupt_enable(temp);
return ret;
}
int gpio_direction_output(unsigned int gpio, int value)
{
unsigned int offset;
int ret=0;
rt_ubase_t temp = rt_hw_interrupt_disable();
ret = gpio_to_base(gpio);
if (ret < 0) {
goto gpio_free;
}
offset = gpio & ((1 << GPIO_GRP_MASK) -1);
if (value) {
gpio_set(offset);
}
else {
gpio_clr(offset);
}
gpio_dirout(offset);
gpio_free:
rt_hw_interrupt_enable(temp);
return ret;
}
int gpio_set_value(unsigned int gpio, int value)
{
unsigned int offset;
int ret=0;
rt_ubase_t temp = rt_hw_interrupt_disable();
ret = gpio_to_base(gpio);
if (ret < 0) {
goto gpio_free;
}
offset = gpio & ((1 << GPIO_GRP_MASK) -1);
if (value) {
gpio_set(offset);
}
else {
gpio_clr(offset);
}
gpio_free:
rt_hw_interrupt_enable(temp);
return ret;
}
int gpio_get_value(unsigned int gpio)
{
unsigned int offset;
int ret=0;
rt_ubase_t temp = rt_hw_interrupt_disable();
ret = gpio_to_base(gpio);
if (ret < 0) {
goto gpio_free;
}
offset = gpio & ((1 << GPIO_GRP_MASK) -1);
ret = gpio_get(offset);
gpio_free:
rt_hw_interrupt_enable(temp);
return ret;
}
/*
* File : gpio.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2011-01-13 weety first version
*/
#ifndef __DM365_GPIO_H
#define __DM365_GPIO_H
#include <dm36x.h>
#define GPIO(X) (X)
#define get_io(r) *((volatile u_int *)(TI81XX_L4_SLOW_IO_ADDRESS(r)))
#define set_io(r,v) *((volatile u_int *)(TI81XX_L4_SLOW_IO_ADDRESS(r))) = (v)
#define and_io(r,v) *((volatile u_int *)(TI81XX_L4_SLOW_IO_ADDRESS(r))) &= (v)
#define or_io(r,v) *((volatile u_int *)(TI81XX_L4_SLOW_IO_ADDRESS(r))) |= (v)
#define v_get_io(r) *((volatile u_int *)(r))
#define v_set_io(r,v) *((volatile u_int *)(r)) = (v)
#define v_and_io(r,v) *((volatile u_int *)(r)) &= (v)
#define v_or_io(r,v) *((volatile u_int *)(r)) |= (v)
enum gpio_intr_mode
{
LEVELDETECT_LOW = 0,
LEVELDETECT_HIGH,
RISINGDETECT,
FALLINGDETECT,
EDGEDETECT //both rising-edge and falling-edge detect
};
enum gpio_intr_req
{
INTR_REQ_A = 0,
INTR_REQ_B
};
enum gpio_intr_num
{
GPIOINT0A = 96,
GPIOINT0B,
GPIOINT1A,
GPIOINT1B,
};
enum pin_func_mod
{
GPIO_MOD = 0x80,
SPI_MOD =0x01,
VP_MOD=0x04,
IIC_MOD=0x20
};
#endif /* __TI814X_GPIO_H */
/*
* File : i2c-davinci.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2011-01-13 weety first version
*/
#include <rtthread.h>
#include <drivers/i2c.h>
#include <dm36x.h>
/* ----- global defines ----------------------------------------------- */
#define BIT(nr) (1UL << (nr))
#define DAVINCI_I2C_TIMEOUT (1*RT_TICK_PER_SECOND)
#define DAVINCI_I2C_MAX_TRIES 2
#define I2C_DAVINCI_INTR_ALL (DAVINCI_I2C_IMR_AAS | \
DAVINCI_I2C_IMR_SCD | \
DAVINCI_I2C_IMR_ARDY | \
DAVINCI_I2C_IMR_NACK | \
DAVINCI_I2C_IMR_AL)
#define DAVINCI_I2C_OAR_REG 0x00
#define DAVINCI_I2C_IMR_REG 0x04
#define DAVINCI_I2C_STR_REG 0x08
#define DAVINCI_I2C_CLKL_REG 0x0c
#define DAVINCI_I2C_CLKH_REG 0x10
#define DAVINCI_I2C_CNT_REG 0x14
#define DAVINCI_I2C_DRR_REG 0x18
#define DAVINCI_I2C_SAR_REG 0x1c
#define DAVINCI_I2C_DXR_REG 0x20
#define DAVINCI_I2C_MDR_REG 0x24
#define DAVINCI_I2C_IVR_REG 0x28
#define DAVINCI_I2C_EMDR_REG 0x2c
#define DAVINCI_I2C_PSC_REG 0x30
#define DAVINCI_I2C_IVR_AAS 0x07
#define DAVINCI_I2C_IVR_SCD 0x06
#define DAVINCI_I2C_IVR_XRDY 0x05
#define DAVINCI_I2C_IVR_RDR 0x04
#define DAVINCI_I2C_IVR_ARDY 0x03
#define DAVINCI_I2C_IVR_NACK 0x02
#define DAVINCI_I2C_IVR_AL 0x01
#define DAVINCI_I2C_STR_BB BIT(12)
#define DAVINCI_I2C_STR_RSFULL BIT(11)
#define DAVINCI_I2C_STR_SCD BIT(5)
#define DAVINCI_I2C_STR_ARDY BIT(2)
#define DAVINCI_I2C_STR_NACK BIT(1)
#define DAVINCI_I2C_STR_AL BIT(0)
#define DAVINCI_I2C_MDR_NACK BIT(15)
#define DAVINCI_I2C_MDR_STT BIT(13)
#define DAVINCI_I2C_MDR_STP BIT(11)
#define DAVINCI_I2C_MDR_MST BIT(10)
#define DAVINCI_I2C_MDR_TRX BIT(9)
#define DAVINCI_I2C_MDR_XA BIT(8)
#define DAVINCI_I2C_MDR_RM BIT(7)
#define DAVINCI_I2C_MDR_IRS BIT(5)
#define DAVINCI_I2C_IMR_AAS BIT(6)
#define DAVINCI_I2C_IMR_SCD BIT(5)
#define DAVINCI_I2C_IMR_XRDY BIT(4)
#define DAVINCI_I2C_IMR_RRDY BIT(3)
#define DAVINCI_I2C_IMR_ARDY BIT(2)
#define DAVINCI_I2C_IMR_NACK BIT(1)
#define DAVINCI_I2C_IMR_AL BIT(0)
#ifdef RT_EDMA_DEBUG
#define i2c_dbg(fmt, ...) rt_kprintf(fmt, ##__VA_ARGS__)
#else
#define i2c_dbg(fmt, ...)
#endif
struct davinci_i2c_dev {
void *base;
struct rt_semaphore completion;
struct clk *clk;
int cmd_err;
rt_uint8_t *buf;
rt_uint32_t buf_len;
int irq;
int stop;
rt_uint8_t terminate;
rt_uint32_t bus_freq;
rt_uint32_t bus_delay;
struct rt_i2c_bus_device *bus;
};
static inline void davinci_i2c_write_reg(struct davinci_i2c_dev *i2c_dev,
int reg, rt_uint16_t val)
{
davinci_writew(val, i2c_dev->base + reg);
}
static inline rt_uint16_t davinci_i2c_read_reg(struct davinci_i2c_dev *i2c_dev, int reg)
{
return davinci_readw(i2c_dev->base + reg);
}
static void udelay (rt_uint32_t us)
{
rt_int32_t i;
for (; us > 0; us--)
{
i = 50000;
while(i > 0)
{
i--;
}
}
}
#if 0
/* Generate a pulse on the i2c clock pin. */
static void generic_i2c_clock_pulse(unsigned int scl_pin)
{
rt_uint16_t i;
if (scl_pin) {
/* Send high and low on the SCL line */
for (i = 0; i < 9; i++) {
gpio_set_value(scl_pin, 0);
udelay(20);
gpio_set_value(scl_pin, 1);
udelay(20);
}
}
}
#endif
/* This routine does i2c bus recovery as specified in the
* i2c protocol Rev. 03 section 3.16 titled "Bus clear"
*/
static void i2c_recover_bus(struct davinci_i2c_dev *dev)
{
rt_uint32_t flag = 0;
i2c_dbg("initiating i2c bus recovery\n");
/* Send NACK to the slave */
flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
flag |= DAVINCI_I2C_MDR_NACK;
/* write the data into mode register */
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
#if 0
if (pdata)
generic_i2c_clock_pulse(pdata->scl_pin);
#endif
/* Send STOP */
flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
flag |= DAVINCI_I2C_MDR_STP;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
}
static inline void davinci_i2c_reset_ctrl(struct davinci_i2c_dev *i2c_dev,
int val)
{
rt_uint16_t w;
w = davinci_i2c_read_reg(i2c_dev, DAVINCI_I2C_MDR_REG);
if (!val) /* put I2C into reset */
w &= ~DAVINCI_I2C_MDR_IRS;
else /* take I2C out of reset */
w |= DAVINCI_I2C_MDR_IRS;
davinci_i2c_write_reg(i2c_dev, DAVINCI_I2C_MDR_REG, w);
}
static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev)
{
rt_uint16_t psc;
rt_uint32_t clk;
rt_uint32_t d;
rt_uint32_t clkh;
rt_uint32_t clkl;
rt_uint32_t input_clock = clk_get_rate(dev->clk);
/* NOTE: I2C Clock divider programming info
* As per I2C specs the following formulas provide prescaler
* and low/high divider values
* input clk --> PSC Div -----------> ICCL/H Div --> output clock
* module clk
*
* output clk = module clk / (PSC + 1) [ (ICCL + d) + (ICCH + d) ]
*
* Thus,
* (ICCL + ICCH) = clk = (input clk / ((psc +1) * output clk)) - 2d;
*
* where if PSC == 0, d = 7,
* if PSC == 1, d = 6
* if PSC > 1 , d = 5
*/
/* get minimum of 7 MHz clock, but max of 12 MHz */
psc = (input_clock / 7000000) - 1;
if ((input_clock / (psc + 1)) > 12000000)
psc++; /* better to run under spec than over */
d = (psc >= 2) ? 5 : 7 - psc;
clk = ((input_clock / (psc + 1)) / (dev->bus_freq * 1000)) - (d << 1);
clkh = clk >> 1;
clkl = clk - clkh;
davinci_i2c_write_reg(dev, DAVINCI_I2C_PSC_REG, psc);
davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh);
davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl);
i2c_dbg("input_clock = %d, CLK = %d\n", input_clock, clk);
}
/*
* This function configures I2C and brings I2C out of reset.
* This function is called during I2C init function. This function
* also gets called if I2C encounters any errors.
*/
static int i2c_davinci_init(struct davinci_i2c_dev *dev)
{
/* put I2C into reset */
davinci_i2c_reset_ctrl(dev, 0);
/* compute clock dividers */
i2c_davinci_calc_clk_dividers(dev);
/* Respond at reserved "SMBus Host" slave address" (and zero);
* we seem to have no option to not respond...
*/
davinci_i2c_write_reg(dev, DAVINCI_I2C_OAR_REG, 0x08);
i2c_dbg("PSC = %d\n",
davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG));
i2c_dbg("CLKL = %d\n",
davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKL_REG));
i2c_dbg("CLKH = %d\n",
davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKH_REG));
i2c_dbg("bus_freq = %dkHz, bus_delay = %d\n",
dev->bus_freq, dev->bus_delay);
/* Take the I2C module out of reset: */
davinci_i2c_reset_ctrl(dev, 1);
/* Enable interrupts */
davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, I2C_DAVINCI_INTR_ALL);
return 0;
}
/*
* Waiting for bus not busy
*/
static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev,
char allow_sleep)
{
unsigned long timeout;
static rt_uint16_t to_cnt;
RT_ASSERT(dev != RT_NULL);
RT_ASSERT(dev->bus != RT_NULL);
timeout = rt_tick_get() + dev->bus->timeout;
while (davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG)
& DAVINCI_I2C_STR_BB) {
if (to_cnt <= DAVINCI_I2C_MAX_TRIES) {
if (rt_tick_get() >= timeout) {
rt_kprintf("timeout waiting for bus ready\n");
to_cnt++;
return -RT_ETIMEOUT;
} else {
to_cnt = 0;
i2c_recover_bus(dev);
i2c_davinci_init(dev);
}
}
if (allow_sleep)
rt_thread_delay(2);
}
return 0;
}
/*
* Low level master read/write transaction. This function is called
* from i2c_davinci_xfer.
*/
static int
i2c_davinci_xfer_msg(struct rt_i2c_bus_device *bus, struct rt_i2c_msg *msg, int stop)
{
struct davinci_i2c_dev *dev = bus->priv;
rt_uint32_t flag;
rt_uint16_t w;
int r;
/* Introduce a delay, required for some boards (e.g Davinci EVM) */
if (dev->bus_delay)
udelay(dev->bus_delay);
/* set the slave address */
davinci_i2c_write_reg(dev, DAVINCI_I2C_SAR_REG, msg->addr);
dev->buf = msg->buf;
dev->buf_len = msg->len;
dev->stop = stop;
davinci_i2c_write_reg(dev, DAVINCI_I2C_CNT_REG, dev->buf_len);
//INIT_COMPLETION(dev->cmd_complete);
dev->cmd_err = 0;
/* Take I2C out of reset and configure it as master */
flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST;
/* if the slave address is ten bit address, enable XA bit */
if (msg->flags & RT_I2C_ADDR_10BIT)
flag |= DAVINCI_I2C_MDR_XA;
if (!(msg->flags & RT_I2C_RD))
flag |= DAVINCI_I2C_MDR_TRX;
if (msg->len == 0)
flag |= DAVINCI_I2C_MDR_RM;
/* Enable receive or transmit interrupts */
w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG);
if (msg->flags & RT_I2C_RD)
w |= DAVINCI_I2C_IMR_RRDY;
else
w |= DAVINCI_I2C_IMR_XRDY;
davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w);
dev->terminate = 0;
/*
* Write mode register first as needed for correct behaviour
* on OMAP-L138, but don't set STT yet to avoid a race with XRDY
* occurring before we have loaded DXR
*/
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
/*
* First byte should be set here, not after interrupt,
* because transmit-data-ready interrupt can come before
* NACK-interrupt during sending of previous message and
* ICDXR may have wrong data
* It also saves us one interrupt, slightly faster
*/
if ((!(msg->flags & RT_I2C_RD)) && dev->buf_len)
{
davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++);
dev->buf_len--;
}
/* Set STT to begin transmit now DXR is loaded */
flag |= DAVINCI_I2C_MDR_STT;
if (stop && msg->len != 0)
flag |= DAVINCI_I2C_MDR_STP;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
r = rt_sem_take(&dev->completion, dev->bus->timeout);
if (r == -RT_ETIMEOUT)
{
rt_kprintf("controller timed out\n");
i2c_recover_bus(dev);
i2c_davinci_init(dev);
dev->buf_len = 0;
return -RT_ETIMEOUT;
}
if (dev->buf_len)
{
/* This should be 0 if all bytes were transferred
* or dev->cmd_err denotes an error.
* A signal may have aborted the transfer.
*/
if (r == RT_EOK)
{
rt_kprintf("abnormal termination buf_len=%i\n",
dev->buf_len);
r = -RT_EIO;
}
dev->terminate = 1;
dev->buf_len = 0;
}
if (r < 0)
return r;
/* no error */
if (!dev->cmd_err)
return msg->len;
/* We have an error */
if (dev->cmd_err & DAVINCI_I2C_STR_AL)
{
i2c_davinci_init(dev);
return -RT_EIO;
}
if (dev->cmd_err & DAVINCI_I2C_STR_NACK)
{
if (msg->flags & RT_I2C_IGNORE_NACK)
return msg->len;
if (stop)
{
w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
w |= DAVINCI_I2C_MDR_STP;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
}
return -RT_EIO;
}
return -RT_EIO;
}
/*
* Prepare controller for a transaction and call i2c_davinci_xfer_msg
*/
static int
i2c_davinci_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], int num)
{
struct davinci_i2c_dev *dev = bus->priv;
int i;
int ret;
i2c_dbg("%s: msgs: %d\n", __func__, num);
ret = i2c_davinci_wait_bus_not_busy(dev, 1);
if (ret < 0)
{
i2c_dbg("timeout waiting for bus ready\n");
return ret;
}
for (i = 0; i < num; i++)
{
ret = i2c_davinci_xfer_msg(bus, &msgs[i], (i == (num - 1)));
i2c_dbg("%s [%d/%d] ret: %d\n", __func__, i + 1, num,
ret);
if (ret < 0)
return ret;
}
return num;
}
static void terminate_read(struct davinci_i2c_dev *dev)
{
rt_uint16_t w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
w |= DAVINCI_I2C_MDR_NACK;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
/* Throw away data */
davinci_i2c_read_reg(dev, DAVINCI_I2C_DRR_REG);
if (!dev->terminate)
rt_kprintf("RDR IRQ while no data requested\n");
}
static void terminate_write(struct davinci_i2c_dev *dev)
{
rt_uint16_t w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
w |= DAVINCI_I2C_MDR_RM | DAVINCI_I2C_MDR_STP;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
if (!dev->terminate)
i2c_dbg("TDR IRQ while no data to send\n");
}
/*
* Interrupt service routine. This gets called whenever an I2C interrupt
* occurs.
*/
static void i2c_davinci_isr(int irq, void *param)
{
struct davinci_i2c_dev *dev = (struct davinci_i2c_dev *)param;
rt_uint32_t stat;
int count = 0;
rt_uint16_t w;
while ((stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG))) {
i2c_dbg("%s: stat=0x%x\n", __func__, stat);
if (count++ == 100) {
rt_kprintf("Too much work in one IRQ\n");
break;
}
switch (stat) {
case DAVINCI_I2C_IVR_AL:
/* Arbitration lost, must retry */
dev->cmd_err |= DAVINCI_I2C_STR_AL;
dev->buf_len = 0;
rt_sem_release(&dev->completion);
break;
case DAVINCI_I2C_IVR_NACK:
dev->cmd_err |= DAVINCI_I2C_STR_NACK;
dev->buf_len = 0;
rt_sem_release(&dev->completion);
break;
case DAVINCI_I2C_IVR_ARDY:
davinci_i2c_write_reg(dev,
DAVINCI_I2C_STR_REG, DAVINCI_I2C_STR_ARDY);
if (((dev->buf_len == 0) && (dev->stop != 0)) ||
(dev->cmd_err & DAVINCI_I2C_STR_NACK)) {
w = davinci_i2c_read_reg(dev,
DAVINCI_I2C_MDR_REG);
w |= DAVINCI_I2C_MDR_STP;
davinci_i2c_write_reg(dev,
DAVINCI_I2C_MDR_REG, w);
}
rt_sem_release(&dev->completion);
break;
case DAVINCI_I2C_IVR_RDR:
if (dev->buf_len) {
*dev->buf++ =
davinci_i2c_read_reg(dev,
DAVINCI_I2C_DRR_REG);
dev->buf_len--;
if (dev->buf_len)
continue;
davinci_i2c_write_reg(dev,
DAVINCI_I2C_STR_REG,
DAVINCI_I2C_IMR_RRDY);
} else {
/* signal can terminate transfer */
terminate_read(dev);
}
break;
case DAVINCI_I2C_IVR_XRDY:
if (dev->buf_len) {
davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG,
*dev->buf++);
dev->buf_len--;
if (dev->buf_len)
continue;
w = davinci_i2c_read_reg(dev,
DAVINCI_I2C_IMR_REG);
w &= ~DAVINCI_I2C_IMR_XRDY;
davinci_i2c_write_reg(dev,
DAVINCI_I2C_IMR_REG,
w);
} else {
/* signal can terminate transfer */
terminate_write(dev);
}
break;
case DAVINCI_I2C_IVR_SCD:
davinci_i2c_write_reg(dev,
DAVINCI_I2C_STR_REG, DAVINCI_I2C_STR_SCD);
rt_sem_release(&dev->completion);
break;
case DAVINCI_I2C_IVR_AAS:
i2c_dbg("Address as slave interrupt\n");
break;
default:
i2c_dbg("Unrecognized irq stat %d\n", stat);
break;
}
}
}
static struct rt_i2c_bus_device_ops bus_ops = {
.master_xfer = i2c_davinci_xfer,
};
int davinci_i2c_init(char *bus_name)
{
struct rt_i2c_bus_device *bus;
struct davinci_i2c_dev *dev;
int r;
bus = rt_malloc(sizeof(struct rt_i2c_bus_device));
if (bus == RT_NULL)
{
rt_kprintf("rt_malloc failed\n");
return -RT_ENOMEM;
}
rt_memset((void *)bus, 0, sizeof(struct rt_i2c_bus_device));
bus->ops = &bus_ops;
bus->timeout = DAVINCI_I2C_TIMEOUT;
dev = rt_malloc(sizeof(struct davinci_i2c_dev));
if (!dev)
{
r = -RT_ENOMEM;
goto err;
}
rt_memset((void *)dev, 0, sizeof(struct davinci_i2c_dev));
rt_sem_init(&dev->completion, "i2c_ack", 0, RT_IPC_FLAG_FIFO);
dev->irq = IRQ_I2C;
dev->clk = clk_get("I2CCLK");
if (dev->clk == RT_NULL) {
r = -RT_ERROR;
goto err1;
}
psc_change_state(DAVINCI_DM365_LPSC_I2C, 3);
dev->base = DAVINCI_I2C_BASE;
dev->bus_freq = 100;
dev->bus_delay = 0;
dev->bus = bus;
bus->priv = dev;
i2c_davinci_init(dev);
rt_hw_interrupt_install(dev->irq, i2c_davinci_isr, (void *)dev, "I2C");
rt_hw_interrupt_umask(dev->irq);
return rt_i2c_bus_device_register(bus, bus_name);
err1:
rt_free(dev);
err:
rt_free(bus);
return r;
}
/*
* File : mii.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2011-03-18 weety first version
*/
#ifndef __MII_H__
#define __MII_H__
/* Generic MII registers. */
#define MII_BMCR 0x00 /* Basic mode control register */
#define MII_BMSR 0x01 /* Basic mode status register */
#define MII_PHYSID1 0x02 /* PHYS ID 1 */
#define MII_PHYSID2 0x03 /* PHYS ID 2 */
#define MII_ADVERTISE 0x04 /* Advertisement control reg */
#define MII_LPA 0x05 /* Link partner ability reg */
#define MII_EXPANSION 0x06 /* Expansion register */
#define MII_CTRL1000 0x09 /* 1000BASE-T control */
#define MII_STAT1000 0x0a /* 1000BASE-T status */
#define MII_ESTATUS 0x0f /* Extended Status */
#define MII_DCOUNTER 0x12 /* Disconnect counter */
#define MII_FCSCOUNTER 0x13 /* False carrier counter */
#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
#define MII_RERRCOUNTER 0x15 /* Receive error counter */
#define MII_SREVISION 0x16 /* Silicon revision */
#define MII_RESV1 0x17 /* Reserved... */
#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
#define MII_PHYADDR 0x19 /* PHY address */
#define MII_RESV2 0x1a /* Reserved... */
#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
#define MII_NCONFIG 0x1c /* Network interface config */
/* Basic mode control register. */
#define BMCR_RESV 0x003f /* Unused... */
#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */
#define BMCR_CTST 0x0080 /* Collision test */
#define BMCR_FULLDPLX 0x0100 /* Full duplex */
#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
#define BMCR_RESET 0x8000 /* Reset the DP83840 */
/* Basic mode status register. */
#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
#define BMSR_JCD 0x0002 /* Jabber detected */
#define BMSR_LSTATUS 0x0004 /* Link status */
#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
#define BMSR_RFAULT 0x0010 /* Remote fault detected */
#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
#define BMSR_RESV 0x00c0 /* Unused... */
#define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */
#define BMSR_100HALF2 0x0200 /* Can do 100BASE-T2 HDX */
#define BMSR_100FULL2 0x0400 /* Can do 100BASE-T2 FDX */
#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
/* Advertisement control register. */
#define ADVERTISE_SLCT 0x001f /* Selector bits */
#define ADVERTISE_CSMA 0x0001 /* Only selector supported */
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
#define ADVERTISE_1000XFULL 0x0020 /* Try for 1000BASE-X full-duplex */
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
#define ADVERTISE_1000XHALF 0x0040 /* Try for 1000BASE-X half-duplex */
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
#define ADVERTISE_1000XPAUSE 0x0080 /* Try for 1000BASE-X pause */
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
#define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */
#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */
#define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */
#define ADVERTISE_RESV 0x1000 /* Unused... */
#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
ADVERTISE_CSMA)
#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
ADVERTISE_100HALF | ADVERTISE_100FULL)
/* Link partner ability register. */
#define LPA_SLCT 0x001f /* Same as advertise selector */
#define LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
#define LPA_1000XFULL 0x0020 /* Can do 1000BASE-X full-duplex */
#define LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
#define LPA_1000XHALF 0x0040 /* Can do 1000BASE-X half-duplex */
#define LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
#define LPA_1000XPAUSE 0x0080 /* Can do 1000BASE-X pause */
#define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
#define LPA_1000XPAUSE_ASYM 0x0100 /* Can do 1000BASE-X pause asym*/
#define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */
#define LPA_PAUSE_CAP 0x0400 /* Can pause */
#define LPA_PAUSE_ASYM 0x0800 /* Can pause asymetrically */
#define LPA_RESV 0x1000 /* Unused... */
#define LPA_RFAULT 0x2000 /* Link partner faulted */
#define LPA_LPACK 0x4000 /* Link partner acked us */
#define LPA_NPAGE 0x8000 /* Next page bit */
#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL)
#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4)
/* Expansion register for auto-negotiation. */
#define EXPANSION_NWAY 0x0001 /* Can do N-way auto-nego */
#define EXPANSION_LCWP 0x0002 /* Got new RX page code word */
#define EXPANSION_ENABLENPAGE 0x0004 /* This enables npage words */
#define EXPANSION_NPCAPABLE 0x0008 /* Link partner supports npage */
#define EXPANSION_MFAULTS 0x0010 /* Multiple faults detected */
#define EXPANSION_RESV 0xffe0 /* Unused... */
#define ESTATUS_1000_TFULL 0x2000 /* Can do 1000BT Full */
#define ESTATUS_1000_THALF 0x1000 /* Can do 1000BT Half */
/* N-way test register. */
#define NWAYTEST_RESV1 0x00ff /* Unused... */
#define NWAYTEST_LOOPBACK 0x0100 /* Enable loopback for N-way */
#define NWAYTEST_RESV2 0xfe00 /* Unused... */
/* 1000BASE-T Control register */
#define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */
#define ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */
/* 1000BASE-T Status register */
#define LPA_1000LOCALRXOK 0x2000 /* Link partner local receiver status */
#define LPA_1000REMRXOK 0x1000 /* Link partner remote receiver status */
#define LPA_1000FULL 0x0800 /* Link partner 1000BASE-T full duplex */
#define LPA_1000HALF 0x0400 /* Link partner 1000BASE-T half duplex */
/* Flow control flags */
#define FLOW_CTRL_TX 0x01
#define FLOW_CTRL_RX 0x02
/**
* mii_nway_result
* @negotiated: value of MII ANAR and'd with ANLPAR
*
* Given a set of MII abilities, check each bit and returns the
* currently supported media, in the priority order defined by
* IEEE 802.3u. We use LPA_xxx constants but note this is not the
* value of LPA solely, as described above.
*
* The one exception to IEEE 802.3u is that 100baseT4 is placed
* between 100T-full and 100T-half. If your phy does not support
* 100T4 this is fine. If your phy places 100T4 elsewhere in the
* priority order, you will need to roll your own function.
*/
rt_inline unsigned int mii_nway_result (unsigned int negotiated)
{
unsigned int ret;
if (negotiated & LPA_100FULL)
ret = LPA_100FULL;
else if (negotiated & LPA_100BASE4)
ret = LPA_100BASE4;
else if (negotiated & LPA_100HALF)
ret = LPA_100HALF;
else if (negotiated & LPA_10FULL)
ret = LPA_10FULL;
else
ret = LPA_10HALF;
return ret;
}
/* The forced speed, 10Mb, 100Mb, gigabit, 2.5Gb, 10GbE. */
#define SPEED_10 10
#define SPEED_100 100
#define SPEED_1000 1000
#define SPEED_2500 2500
#define SPEED_10000 10000
#endif /* __MII_H__ */
此差异已折叠。
/*
* File : mmcsd.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2011-01-13 weety first version
*/
#ifndef __DAVINCI_MMC_H__
#define __DAVINCI_MMC_H__
/* DAVINCI_MMCCTL definitions */
#define MMCCTL_DATRST (1 << 0)
#define MMCCTL_CMDRST (1 << 1)
#define MMCCTL_WIDTH_8_BIT (1 << 8)
#define MMCCTL_WIDTH_4_BIT (1 << 2)
#define MMCCTL_DATEG_DISABLED (0 << 6)
#define MMCCTL_DATEG_RISING (1 << 6)
#define MMCCTL_DATEG_FALLING (2 << 6)
#define MMCCTL_DATEG_BOTH (3 << 6)
#define MMCCTL_PERMDR_LE (0 << 9)
#define MMCCTL_PERMDR_BE (1 << 9)
#define MMCCTL_PERMDX_LE (0 << 10)
#define MMCCTL_PERMDX_BE (1 << 10)
/* DAVINCI_MMCCLK definitions */
#define MMCCLK_CLKEN (1 << 8)
#define MMCCLK_CLKRT_MASK (0xFF << 0)
/* IRQ bit definitions, for DAVINCI_MMCST0 and DAVINCI_MMCIM */
#define MMCST0_DATDNE (1 << 0) /* data done */
#define MMCST0_BSYDNE (1 << 1) /* busy done */
#define MMCST0_RSPDNE (1 << 2) /* command done */
#define MMCST0_TOUTRD (1 << 3) /* data read timeout */
#define MMCST0_TOUTRS (1 << 4) /* command response timeout */
#define MMCST0_CRCWR (1 << 5) /* data write CRC error */
#define MMCST0_CRCRD (1 << 6) /* data read CRC error */
#define MMCST0_CRCRS (1 << 7) /* command response CRC error */
#define MMCST0_DXRDY (1 << 9) /* data transmit ready (fifo empty) */
#define MMCST0_DRRDY (1 << 10) /* data receive ready (data in fifo)*/
#define MMCST0_DATED (1 << 11) /* DAT3 edge detect */
#define MMCST0_TRNDNE (1 << 12) /* transfer done */
/* DAVINCI_MMCST1 definitions */
#define MMCST1_BUSY (1 << 0)
/* DAVINCI_MMCCMD definitions */
#define MMCCMD_CMD_MASK (0x3F << 0)
#define MMCCMD_PPLEN (1 << 7)
#define MMCCMD_BSYEXP (1 << 8)
#define MMCCMD_RSPFMT_MASK (3 << 9)
#define MMCCMD_RSPFMT_NONE (0 << 9)
#define MMCCMD_RSPFMT_R1456 (1 << 9)
#define MMCCMD_RSPFMT_R2 (2 << 9)
#define MMCCMD_RSPFMT_R3 (3 << 9)
#define MMCCMD_DTRW (1 << 11)
#define MMCCMD_STRMTP (1 << 12)
#define MMCCMD_WDATX (1 << 13)
#define MMCCMD_INITCK (1 << 14)
#define MMCCMD_DCLR (1 << 15)
#define MMCCMD_DMATRIG (1 << 16)
/* DAVINCI_MMCFIFOCTL definitions */
#define MMCFIFOCTL_FIFORST (1 << 0)
#define MMCFIFOCTL_FIFODIR_WR (1 << 1)
#define MMCFIFOCTL_FIFODIR_RD (0 << 1)
#define MMCFIFOCTL_FIFOLEV (1 << 2) /* 0 = 128 bits, 1 = 256 bits */
#define MMCFIFOCTL_ACCWD_4 (0 << 3) /* access width of 4 bytes */
#define MMCFIFOCTL_ACCWD_3 (1 << 3) /* access width of 3 bytes */
#define MMCFIFOCTL_ACCWD_2 (2 << 3) /* access width of 2 bytes */
#define MMCFIFOCTL_ACCWD_1 (3 << 3) /* access width of 1 byte */
/* DAVINCI_SDIOST0 definitions */
#define SDIOST0_DAT1_HI (1 << 0)
#define SDIOST0_INTPRD (1 << 1)
#define SDIOST0_RDWTST (1 << 2)
/* DAVINCI_SDIOIEN definitions */
#define SDIOIEN_IOINTEN (1 << 0)
#define SDIOIEN_RWSEN (1 << 1)
/* DAVINCI_SDIOIST definitions */
#define SDIOIST_IOINT (1 << 0)
#define SDIOIST_RWS (1 << 1)
/* MMCSD Init clock in Hz in opendrain mode */
#define MMCSD_INIT_CLOCK 200000
#define MAX_CCNT ((1 << 16) - 1)
#define MAX_NR_SG 16
#define MMC_DATA_WRITE (1 << 8)
#define MMC_DATA_READ (1 << 9)
#define MMC_DATA_STREAM (1 << 10)
typedef struct {
volatile rt_uint32_t MMCCTL;
volatile rt_uint32_t MMCCLK;
volatile rt_uint32_t MMCST0;
volatile rt_uint32_t MMCST1;
volatile rt_uint32_t MMCIM;
volatile rt_uint32_t MMCTOR;
volatile rt_uint32_t MMCTOD;
volatile rt_uint32_t MMCBLEN;
volatile rt_uint32_t MMCNBLK;
volatile rt_uint32_t MMCNBLC;
volatile rt_uint32_t MMCDRR;
volatile rt_uint32_t MMCDXR;
volatile rt_uint32_t MMCCMD;
volatile rt_uint32_t MMCARGHL;
volatile rt_uint32_t MMCRSP01;
volatile rt_uint32_t MMCRSP23;
volatile rt_uint32_t MMCRSP45;
volatile rt_uint32_t MMCRSP67;
volatile rt_uint32_t MMCDRSP;
volatile rt_uint32_t reserved0;
volatile rt_uint32_t MMCCIDX;
volatile rt_uint32_t reserved1[4];
volatile rt_uint32_t SDIOCTL;
volatile rt_uint32_t SDIOST0;
volatile rt_uint32_t SDIOIEN;
volatile rt_uint32_t SDIOIST;
volatile rt_uint32_t MMCFIFOCTL;
}mmcsd_regs_t;
extern rt_int32_t rt_hw_mmcsd_init(void);
#endif
此差异已折叠。
/*
* File : spi-davinci.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2011-01-13 weety first version
*/
#ifndef __DAVINCI_SPI_H
#define __DAVINCI_SPI_H
typedef unsigned long u32;
typedef unsigned short u16;
typedef unsigned char u8;
typedef unsigned int bool;
#define SPI_INTERN_CS 0xFF
enum {
SPI_VERSION_1, /* For DM355/DM365/DM6467 */
SPI_VERSION_2, /* For DA8xx */
};
/**
* davinci_spi_config - Per-chip-select configuration for SPI slave devices
*
* @wdelay: amount of delay between transmissions. Measured in number of
* SPI module clocks.
* @odd_parity: polarity of parity flag at the end of transmit data stream.
* 0 - odd parity, 1 - even parity.
* @parity_enable: enable transmission of parity at end of each transmit
* data stream.
* @io_type: type of IO transfer. Choose between polled, interrupt and DMA.
* @timer_disable: disable chip-select timers (setup and hold)
* @c2tdelay: chip-select setup time. Measured in number of SPI module clocks.
* @t2cdelay: chip-select hold time. Measured in number of SPI module clocks.
* @t2edelay: transmit data finished to SPI ENAn pin inactive time. Measured
* in number of SPI clocks.
* @c2edelay: chip-select active to SPI ENAn signal active time. Measured in
* number of SPI clocks.
*/
struct davinci_spi_config {
u8 wdelay;
u8 odd_parity;
u8 parity_enable;
#define SPI_IO_TYPE_INTR 0
#define SPI_IO_TYPE_POLL 1
#define SPI_IO_TYPE_DMA 2
u8 io_type;
u8 timer_disable;
u8 c2tdelay;
u8 t2cdelay;
u8 t2edelay;
u8 c2edelay;
};
extern int rt_hw_spi_init(void);
#endif /* __DAVINCI_SPI_H */
Import('RTT_ROOT')
from building import *
cwd = GetCurrentDir()
src = Split("""
start_gcc.S
dm365.c
dma.c
findbit.S
interrupt.c
psc.c
reset.c
system_clock.c
trap.c
""")
# The set of source files associated with this SConscript file.
path = [cwd]
group = DefineGroup('Startup', src, depend = [''], CPPPATH = path)
Return('group')
/*
* File : dm365.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2010-11-13 weety first version
*/
#include <edma.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
static rt_uint32_t commonrate;
static rt_uint32_t div_by_four;
static rt_uint32_t div_by_six;
static rt_uint32_t armrate;
static rt_uint32_t fixedrate;
static rt_uint32_t ddrrate;
static rt_uint32_t voicerate;
static rt_uint32_t mmcsdrate;
static rt_uint32_t vpssrate, vencrate_sd, vencrate_hd;
/* Four Transfer Controllers on DM365 */
static const rt_int8_t
dm365_queue_tc_mapping[][2] = {
/* {event queue no, TC no} */
{0, 0},
{1, 1},
{2, 2},
{3, 3},
{-1, -1},
};
static const rt_int8_t
dm365_queue_priority_mapping[][2] = {
/* {event queue no, Priority} */
{0, 7},
{1, 7},
{2, 7},
{3, 0},
{-1, -1},
};
static struct edma_soc_info edma_cc0_info = {
.n_channel = 64,
.n_region = 4,
.n_slot = 256,
.n_tc = 4,
.n_cc = 1,
.queue_tc_mapping = dm365_queue_tc_mapping,
.queue_priority_mapping = dm365_queue_priority_mapping,
.default_queue = EVENTQ_3,
};
static struct edma_soc_info *dm365_edma_info[EDMA_MAX_CC] = {
&edma_cc0_info,
};
static rt_list_t clocks;
struct clk {
char name[32];
rt_uint32_t *rate_hz;
struct clk *parent;
rt_list_t node;
};
static struct clk davinci_dm365_clks[] = {
{
.name = "ARMCLK",
.rate_hz = &armrate,
},
{
.name = "UART0",
.rate_hz = &fixedrate,
},
{
.name = "UART1",
.rate_hz = &commonrate,
},
{
.name = "HPI",
.rate_hz = &commonrate,
},
{
.name = "EMACCLK",
.rate_hz = &commonrate,
},
{
.name = "I2CCLK",
.rate_hz = &fixedrate,
},
{
.name = "McBSPCLK",
.rate_hz = &commonrate,
},
{
.name = "MMCSDCLK0",
.rate_hz = &mmcsdrate,
},
{
.name = "MMCSDCLK1",
.rate_hz = &mmcsdrate,
},
{
.name = "SPICLK",
.rate_hz = &commonrate,
},
{
.name = "gpio",
.rate_hz = &commonrate,
},
{
.name = "AEMIFCLK",
.rate_hz = &commonrate,
},
{
.name = "PWM0_CLK",
.rate_hz = &fixedrate,
},
{
.name = "PWM1_CLK",
.rate_hz = &fixedrate,
},
{
.name = "PWM2_CLK",
.rate_hz = &fixedrate,
},
{
.name = "PWM3_CLK",
.rate_hz = &fixedrate,
},
{
.name = "USBCLK",
.rate_hz = &fixedrate,
},
{
.name = "VOICECODEC_CLK",
.rate_hz = &voicerate,
},
{
.name = "RTC_CLK",
.rate_hz = &fixedrate,
},
{
.name = "KEYSCAN_CLK",
.rate_hz = &fixedrate,
},
{
.name = "ADCIF_CLK",
.rate_hz = &fixedrate,
},
};
/* clocks cannot be de-registered no refcounting necessary */
struct clk *clk_get(const char *id)
{
struct clk *clk;
rt_list_t *list;
for (list = (&clocks)->next; list != &clocks; list = list->next)
{
clk = (struct clk *)rt_list_entry(list, struct clk, node);
if (rt_strcmp(id, clk->name) == 0)
return clk;
}
return RT_NULL;
}
rt_uint32_t clk_get_rate(struct clk *clk)
{
rt_uint32_t flags;
rt_uint32_t *rate;
for (;;) {
rate = clk->rate_hz;
if (rate || !clk->parent)
break;
clk = clk->parent;
}
return *rate;
}
void clk_register(struct clk *clk)
{
rt_list_insert_after(&clocks, &clk->node);
}
int davinci_register_clks(struct clk *clk_list, int num_clks)
{
struct clk *clkp;
int i;
for (i = 0, clkp = clk_list; i < num_clks; i++, clkp++)
{
//rt_kprintf("1:%s\n", clkp->name);
clk_register(clkp);
//rt_kprintf("2:%s\n", clkp->name);
}
return 0;
}
/* PLL/Reset register offsets */
#define PLLM 0x110
#define PREDIV 0x114
#define PLLDIV2 0x11C
#define POSTDIV 0x128
#define PLLDIV4 0x160
#define PLLDIV5 0x164
#define PLLDIV6 0x168
#define PLLDIV7 0x16C
#define PLLDIV8 0x170
int davinci_clk_init(void)
{
struct clk *clk_list;
int num_clks;
rt_uint32_t pll0_mult, pll1_mult;
unsigned long prediv, postdiv;
unsigned long pll_rate;
unsigned long pll_div2, pll_div4, pll_div5,
pll_div6, pll_div7, pll_div8;
rt_list_init(&clocks);
//davinci_psc_register(davinci_psc_base, 1);
pll0_mult = davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PLLM);
pll1_mult = davinci_readl(DAVINCI_PLL_CNTRL1_BASE + PLLM);
commonrate = ((pll0_mult + 1) * 27000000) / 6;
armrate = ((pll0_mult + 1) * 27000000) / 2;
fixedrate = 24000000;
/* Read PLL0 configuration */
prediv = (davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PREDIV) &
0x1f) + 1;
postdiv = (davinci_readl(DAVINCI_PLL_CNTRL0_BASE + POSTDIV) &
0x1f) + 1;
/* PLL0 dividers */
pll_div4 = (davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PLLDIV4) &
0x1f) + 1; /* EDMA, EMAC, config, common */
pll_div5 = (davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PLLDIV5) &
0x1f) + 1; /* VPSS */
pll_div6 = (davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PLLDIV6) &
0x1f) + 1; /* VENC */
pll_div7 = (davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PLLDIV7) &
0x1f) + 1; /* DDR */
pll_div8 = (davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PLLDIV8) &
0x1f) + 1; /* MMC/SD */
pll_rate = ((fixedrate / prediv) * (2 * pll0_mult)) / postdiv;
commonrate = pll_rate / pll_div4; /* 486/4 = 121.5MHz */
vpssrate = pll_rate / pll_div5; /* 486/2 = 243MHz */
vencrate_sd = pll_rate / pll_div6; /* 486/18 = 27MHz */
ddrrate = pll_rate / pll_div7; /* 486/2 = 243MHz */
mmcsdrate = pll_rate / pll_div8; /* 486/4 = 121.5MHz */
rt_kprintf(
"PLL0: fixedrate: %d, commonrate: %d, vpssrate: %d\n",
fixedrate, commonrate, vpssrate);
rt_kprintf(
"PLL0: vencrate_sd: %d, ddrrate: %d mmcsdrate: %d\n",
vencrate_sd, (ddrrate/2), mmcsdrate);
/* Read PLL1 configuration */
prediv = (davinci_readl(DAVINCI_PLL_CNTRL1_BASE + PREDIV) &
0x1f) + 1;
postdiv = (davinci_readl(DAVINCI_PLL_CNTRL1_BASE + POSTDIV) &
0x1f) + 1;
pll_rate = ((fixedrate / prediv) * (2 * pll1_mult)) / postdiv;
/* PLL1 dividers */
pll_div2 = (davinci_readl(DAVINCI_PLL_CNTRL1_BASE + PLLDIV2) &
0x1f) + 1; /* ARM */
pll_div4 = (davinci_readl(DAVINCI_PLL_CNTRL1_BASE + PLLDIV4) &
0x1f) + 1; /* VOICE */
pll_div5 = (davinci_readl(DAVINCI_PLL_CNTRL1_BASE + PLLDIV5) &
0x1f) + 1; /* VENC */
armrate = pll_rate / pll_div2; /* 594/2 = 297MHz */
voicerate = pll_rate / pll_div4; /* 594/6 = 99MHz */
vencrate_hd = pll_rate / pll_div5; /* 594/8 = 74.25MHz */
rt_kprintf(
"PLL1: armrate: %d, voicerate: %d, vencrate_hd: %d\n",
armrate, voicerate, vencrate_hd);
clk_list = davinci_dm365_clks;
num_clks = ARRAY_SIZE(davinci_dm365_clks);
return davinci_register_clks(clk_list, num_clks);
}
void platform_init(void)
{
edma_init(dm365_edma_info);
}
/* Reset board using the watchdog timer */
void reset_system(void)
{
rt_uint32_t tgcr, wdtcr;
rt_uint32_t base = DAVINCI_WDOG_BASE;
/* Disable, internal clock source */
davinci_writel(0, base + TCR);
/* Reset timer, set mode to 64-bit watchdog, and unreset */
davinci_writel(0, base + TGCR);
tgcr = (TGCR_TIMMODE_64BIT_WDOG << TGCR_TIMMODE_SHIFT) |
(TGCR_UNRESET << TGCR_TIM12RS_SHIFT) |
(TGCR_UNRESET << TGCR_TIM34RS_SHIFT);
davinci_writel(tgcr, base + TGCR);
/* Clear counter and period regs */
davinci_writel(0, base + TIM12);
davinci_writel(0, base + TIM34);
davinci_writel(0, base + PRD12);
davinci_writel(0, base + PRD34);
/* Enable periodic mode */
davinci_writel(TCR_ENAMODE_PERIODIC << ENAMODE12_SHIFT, base + TCR);
/* Put watchdog in pre-active state */
wdtcr = (WDTCR_WDKEY_SEQ0 << WDTCR_WDKEY_SHIFT) |
(WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT);
davinci_writel(wdtcr, base + WDTCR);
/* Put watchdog in active state */
wdtcr = (WDTCR_WDKEY_SEQ1 << WDTCR_WDKEY_SHIFT) |
(WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT);
davinci_writel(wdtcr, base + WDTCR);
/*
* Write an invalid value to the WDKEY field to trigger
* a watchdog reset.
*/
wdtcr = 0xDEADBEEF;
davinci_writel(wdtcr, base + WDTCR);
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
/*
* File : system_clock.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2010-11-13 weety first version
*/
#include <rtthread.h>
#include "dm36x.h"
/**
* @brief System Clock Configuration
*/
void rt_hw_clock_init(void)
{
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -59,6 +59,11 @@ extern "C"{
#define RT_SPI_MODE_MASK (RT_SPI_CPHA | RT_SPI_CPOL | RT_SPI_MSB)
#define RT_SPI_CS_HIGH (1<<4) /* Chipselect active high */
#define RT_SPI_NO_CS (1<<5) /* No chipselect */
#define RT_SPI_3WIRE (1<<6) /* SI/SO pin shared */
#define RT_SPI_READY (1<<7) /* Slave pulls low to pause */
/**
* SPI message structure
*/
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册