1
1

Initial dump from Zyxel

This commit is contained in:
2026-04-17 17:00:52 +02:00
commit 81fec250f4
23116 changed files with 5231237 additions and 0 deletions
@@ -0,0 +1,39 @@
include $(TOPDIR)/config.mk
LIB = $(obj)lib$(SOC).a
COBJS-y = meminit.o
ifeq ($(BOARD), ap121)
COBJS-y += hornet_serial.o
SOBJS += hornet_ddr_init.o
else
COBJS-y += ar7240_serial.o
endif
ifneq ($(BUILD_EMU), )
COBJS-y += hornet_ag7240.o
else
ifneq ($(CONFIG_SOC_AG934X),)
COBJS-y += ag934x.o
else
COBJS-y += ag7240.o
endif
endif
SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS-y))
all: $(obj).depend $(LIB)
$(LIB): $(OBJS)
$(AR) $(ARFLAGS) $@ $(OBJS)
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################
@@ -0,0 +1,59 @@
include $(TOPDIR)/config.mk
LIB = $(obj)lib$(SOC).a
COBJS-y = meminit.o
ifeq ($(BOARD), ap121)
COBJS-y += hornet_serial.o
SOBJS += hornet_ddr_init.o
else
COBJS-y += ar7240_serial.o
endif
ifneq ($(BUILD_EMU), )
COBJS-y += hornet_ag7240.o
else
ifneq ($(findstring db12x,$(BOARD)),)
COBJS-y += ag934x.o
else
ifneq ($(findstring wah132,$(BOARD)),)
COBJS-y += ag934x.o
else
ifneq ($(findstring reh132,$(BOARD)),)
COBJS-y += ag934x.o
else
ifneq ($(findstring dhp,$(BOARD)),)
COBJS-y += ag934x.o
else
ifneq ($(findstring aph,$(BOARD)),)
COBJS-y += ag934x.o
else
ifneq ($(findstring ap123,$(BOARD)),)
COBJS-y += ag934x.o
else
COBJS-y += ag7240.o
endif
endif
endif
endif
endif
endif
endif
SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS-y))
all: $(obj).depend $(LIB)
$(LIB): $(OBJS)
$(AR) $(ARFLAGS) $@ $(OBJS)
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################
@@ -0,0 +1,722 @@
#include <config.h>
#include <common.h>
#include <malloc.h>
#include <net.h>
#include <command.h>
#include <asm/io.h>
#include <asm/addrspace.h>
#include <asm/types.h>
#include "ar7240_soc.h"
#include "ag7240.h"
#include "ag7240_phy.h"
#ifdef CONFIG_MII
#include <miiphy.h>
#endif
#define ag7240_unit2mac(_unit) ag7240_macs[(_unit)]
#define ag7240_name2mac(name) strcmp(name,"eth0") ? ag7240_unit2mac(1) : ag7240_unit2mac(0)
uint16_t ag7240_miiphy_read(char *devname, uint32_t phaddr,
uint8_t reg);
void ag7240_miiphy_write(char *devname, uint32_t phaddr,
uint8_t reg, uint16_t data);
ag7240_mac_t *ag7240_macs[CFG_AG7240_NMACS];
extern void ar7240_sys_frequency(u32 *cpu_freq, u32 *ddr_freq, u32 *ahb_freq);
#ifdef CFG_ATHRS26_PHY
extern int athrs26_phy_setup(int unit);
extern int athrs26_phy_is_up(int unit);
extern int athrs26_phy_is_fdx(int unit);
extern int athrs26_phy_speed(int unit);
extern void athrs26_reg_init(void);
extern void athrs26_reg_init_lan(void);
extern int athrs26_mdc_check(void);
#endif
#ifdef CFG_ATHRS27_PHY
extern int athrs27_phy_setup(int unit);
extern int athrs27_phy_is_up(int unit);
extern int athrs27_phy_is_fdx(int unit);
extern int athrs27_phy_speed(int unit);
extern void athrs27_reg_init(void);
extern void athrs27_reg_init_lan(void);
extern int athrs27_mdc_check(void);
#endif
#ifdef CONFIG_F1E_PHY
extern int athr_phy_setup(int unit);
extern int athr_phy_is_up(int unit);
extern int athr_phy_is_fdx(int unit);
extern int athr_phy_speed(int unit);
extern void athr_reg_init(void);
#endif
static int
ag7240_send(struct eth_device *dev, volatile void *packet, int length)
{
int i;
ag7240_mac_t *mac = (ag7240_mac_t *)dev->priv;
ag7240_desc_t *f = mac->fifo_tx[mac->next_tx];
f->pkt_size = length;
f->res1 = 0;
f->pkt_start_addr = virt_to_phys(packet);
ag7240_tx_give_to_dma(f);
flush_cache((u32) packet, length);
ag7240_reg_wr(mac, AG7240_DMA_TX_DESC, virt_to_phys(f));
ag7240_reg_wr(mac, AG7240_DMA_TX_CTRL, AG7240_TXE);
for (i = 0; i < MAX_WAIT; i++) {
udelay(10);
if (!ag7240_tx_owned_by_dma(f))
break;
}
if (i == MAX_WAIT)
printf("Tx Timed out\n");
f->pkt_start_addr = 0;
f->pkt_size = 0;
if (++mac->next_tx >= NO_OF_TX_FIFOS)
mac->next_tx = 0;
return (0);
}
static int ag7240_recv(struct eth_device *dev)
{
int length;
ag7240_desc_t *f;
ag7240_mac_t *mac;
mac = (ag7240_mac_t *)dev->priv;
for (;;) {
f = mac->fifo_rx[mac->next_rx];
if (ag7240_rx_owned_by_dma(f))
break;
length = f->pkt_size;
NetReceive(NetRxPackets[mac->next_rx] , length - 4);
flush_cache((u32) NetRxPackets[mac->next_rx] , PKTSIZE_ALIGN);
ag7240_rx_give_to_dma(f);
if (++mac->next_rx >= NO_OF_RX_FIFOS)
mac->next_rx = 0;
}
if (!(ag7240_reg_rd(mac, AG7240_DMA_RX_CTRL))) {
ag7240_reg_wr(mac, AG7240_DMA_RX_DESC, virt_to_phys(f));
ag7240_reg_wr(mac, AG7240_DMA_RX_CTRL, 1);
}
return (0);
}
void ag7240_mii_setup(ag7240_mac_t *mac)
{
u32 mgmt_cfg_val;
u32 cpu_freq,ddr_freq,ahb_freq;
u32 check_cnt,revid_val;
#ifdef CFG_ATHRS27_PHY
if (is_wasp()) {
printf("WASP ----> S27 PHY \n");
mgmt_cfg_val = 2;
ar7240_reg_wr(0xb8050024, 0x271); // 25MHz ref clock
//ar7240_reg_wr(0xb8050024, 0x570); // 40MHz ref clock
ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
return;
}
#endif
#ifdef CONFIG_AR7242_S16_PHY
if (is_wasp()) {
printf("WASP ----> S16 PHY *\n");
mgmt_cfg_val = 4;
if(mac->mac_unit == 0)
ar7240_reg_wr(AG7240_ETH_CFG, AG7240_ETH_CFG_RGMII_GE0);
ar7240_reg_rmw_clear(AG7240_ETH_SWITCH_CLK_SPARE, (1 << 6));
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
return;
}
#endif
#ifdef CONFIG_F1E_PHY
if (is_wasp()) {
printf("WASP ----> F1 PHY *\n");
mgmt_cfg_val = 6;
if(mac->mac_unit == 0)
ar7240_reg_wr(AG7240_ETH_CFG, AG7240_ETH_CFG_RGMII_GE0);
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
return;
}
#endif
if ((ar7240_reg_rd(AR7240_REV_ID) & AR7240_REV_ID_MASK) == AR7240_REV_1_2) {
mgmt_cfg_val = 0x2;
if (mac->mac_unit == 0) {
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
}
}
else {
ar7240_sys_frequency(&cpu_freq, &ddr_freq, &ahb_freq);
switch (ahb_freq/1000000) {
case 150:
mgmt_cfg_val = 0x7;
break;
case 175:
mgmt_cfg_val = 0x5;
break;
case 200:
mgmt_cfg_val = 0x4;
break;
case 210:
mgmt_cfg_val = 0x9;
break;
case 220:
mgmt_cfg_val = 0x9;
break;
default:
mgmt_cfg_val = 0x7;
}
if ((is_ar7241() || is_ar7242())) {
/* External MII mode */
if (mac->mac_unit == 0 && is_ar7242()) {
mgmt_cfg_val = 0x6;
ar7240_reg_rmw_set(AG7240_ETH_CFG, AG7240_ETH_CFG_RGMII_GE0);
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
}
/* Virian */
mgmt_cfg_val = 0x4;
ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
printf("Virian MDC CFG Value ==> %x\n",mgmt_cfg_val);
}
else if(is_ar933x()){
//GE0 receives Rx/Tx clock, and use S26 phy
ar7240_reg_rmw_set(AG7240_ETH_CFG, AG7240_ETH_CFG_MII_GE0_SLAVE);
mgmt_cfg_val = 0xF;
if (mac->mac_unit == 1) {
check_cnt = 0;
while (check_cnt++ < 10) {
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
#ifdef CFG_ATHRS26_PHY
if(athrs26_mdc_check() == 0)
break;
#endif
}
if(check_cnt == 11)
printf("%s: MDC check failed\n", __func__);
}
}
else { /* Python 1.0 & 1.1 */
if (mac->mac_unit == 0) {
check_cnt = 0;
while (check_cnt++ < 10) {
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
#ifdef CFG_ATHRS26_PHY
if(athrs26_mdc_check() == 0)
break;
#endif
}
if(check_cnt == 11)
printf("%s: MDC check failed\n", __func__);
}
}
}
}
static void ag7240_hw_start(ag7240_mac_t *mac)
{
if(mac->mac_unit)
{
ag7240_reg_wr(mac, AG7240_MAC_CFG1, (AG7240_MAC_CFG1_RX_EN |
AG7240_MAC_CFG1_TX_EN));
ag7240_reg_rmw_set(mac, AG7240_MAC_CFG2, (AG7240_MAC_CFG2_PAD_CRC_EN |
AG7240_MAC_CFG2_LEN_CHECK | AG7240_MAC_CFG2_IF_1000));
}
else {
ag7240_reg_wr(mac, AG7240_MAC_CFG1, (AG7240_MAC_CFG1_RX_EN |
AG7240_MAC_CFG1_TX_EN));
ag7240_reg_rmw_set(mac, AG7240_MAC_CFG2, (AG7240_MAC_CFG2_PAD_CRC_EN |
AG7240_MAC_CFG2_LEN_CHECK | AG7240_MAC_CFG2_IF_10_100));
}
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_0, 0x1f00);
ag7240_mii_setup(mac);
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_1, 0x10ffff);
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_2, 0xAAA0555);
ag7240_reg_rmw_set(mac, AG7240_MAC_FIFO_CFG_4, 0x3ffff);
/*
* Setting Drop CRC Errors, Pause Frames,Length Error frames
* and Multi/Broad cast frames.
*/
#ifdef AG7240_BROADCAST_ENABLE
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_5, 0xe6be2);
#else
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_5, 0x7eccf);
#endif
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_3, 0x1f00140);
printf(": cfg1 %#x cfg2 %#x\n", ag7240_reg_rd(mac, AG7240_MAC_CFG1),
ag7240_reg_rd(mac, AG7240_MAC_CFG2));
}
static int ag7240_check_link(ag7240_mac_t *mac)
{
u32 link, duplex, speed, fdx;
ag7240_phy_link(mac->mac_unit, &link);
ag7240_phy_duplex(mac->mac_unit, &duplex);
ag7240_phy_speed(mac->mac_unit, &speed);
mac->link = link;
#ifdef SUPPORT_PLC
if(strcmp(mac->dev->name, "eth0") == 0) {
printf("ag7240_check_link: %s link forced down\n",mac->dev->name);
return 0;
}
#endif
if(!mac->link) {
printf("%s link down\n",mac->dev->name);
return 0;
}
switch (speed)
{
case _1000BASET:
ag7240_set_mac_if(mac, 1);
ag7240_reg_rmw_set(mac, AG7240_MAC_FIFO_CFG_5, (1 << 19));
if (is_ar7242() && (mac->mac_unit == 0)) {
ar7240_reg_wr(AR7242_ETH_XMII_CONFIG,0x1c000000);
}
#ifdef CONFIG_F1E_PHY
if (is_wasp() && (mac->mac_unit == 0)) {
ar7240_reg_wr(AR7242_ETH_XMII_CONFIG,0x0e000000);
}
#else
if (is_wasp() && (mac->mac_unit == 0)) {
ar7240_reg_wr(AR7242_ETH_XMII_CONFIG,0x06000000);
}
#endif
break;
case _100BASET:
ag7240_set_mac_if(mac, 0);
ag7240_set_mac_speed(mac, 1);
ag7240_reg_rmw_clear(mac, AG7240_MAC_FIFO_CFG_5, (1 << 19));
if ((is_ar7242() || is_wasp()) && (mac->mac_unit == 0))
ar7240_reg_wr(AR7242_ETH_XMII_CONFIG,0x0101);
break;
case _10BASET:
ag7240_set_mac_if(mac, 0);
ag7240_set_mac_speed(mac, 0);
ag7240_reg_rmw_clear(mac, AG7240_MAC_FIFO_CFG_5, (1 << 19));
if ((is_ar7242() || is_wasp()) && (mac->mac_unit == 0))
ar7240_reg_wr(AR7242_ETH_XMII_CONFIG,0x1616);
break;
default:
printf("Invalid speed detected\n");
return 0;
}
if (mac->link && (duplex == mac->duplex) && (speed == mac->speed))
return 1;
mac->duplex = duplex;
mac->speed = speed;
printf("dup %d speed %d\n", duplex, speed);
ag7240_set_mac_duplex(mac,duplex);
return 1;
}
/*
* For every command we re-setup the ring and start with clean h/w rx state
*/
static int ag7240_clean_rx(struct eth_device *dev, bd_t * bd)
{
int i;
ag7240_desc_t *fr;
ag7240_mac_t *mac = (ag7240_mac_t*)dev->priv;
if (!ag7240_check_link(mac))
return 0;
mac->next_rx = 0;
for (i = 0; i < NO_OF_RX_FIFOS; i++) {
fr = mac->fifo_rx[i];
fr->pkt_start_addr = virt_to_phys(NetRxPackets[i]);
flush_cache((u32) NetRxPackets[i], PKTSIZE_ALIGN);
ag7240_rx_give_to_dma(fr);
}
ag7240_reg_wr(mac, AG7240_DMA_RX_DESC, virt_to_phys(mac->fifo_rx[0]));
ag7240_reg_wr(mac, AG7240_DMA_RX_CTRL, AG7240_RXE); /* rx start */
if(!is_ar933x())
udelay(1000 * 1000);
return 1;
}
static int ag7240_alloc_fifo(int ndesc, ag7240_desc_t ** fifo)
{
int i;
u32 size;
uchar *p = NULL;
size = sizeof(ag7240_desc_t) * ndesc;
size += CONFIG_SYS_CACHELINE_SIZE - 1;
if ((p = malloc(size)) == NULL) {
printf("Cant allocate fifos\n");
return -1;
}
p = (uchar *) (((u32) p + CONFIG_SYS_CACHELINE_SIZE - 1) &
~(CONFIG_SYS_CACHELINE_SIZE - 1));
p = UNCACHED_SDRAM(p);
for (i = 0; i < ndesc; i++)
fifo[i] = (ag7240_desc_t *) p + i;
return 0;
}
static int ag7240_setup_fifos(ag7240_mac_t *mac)
{
int i;
if (ag7240_alloc_fifo(NO_OF_TX_FIFOS, mac->fifo_tx))
return 1;
for (i = 0; i < NO_OF_TX_FIFOS; i++) {
mac->fifo_tx[i]->next_desc = (i == NO_OF_TX_FIFOS - 1) ?
virt_to_phys(mac->fifo_tx[0]) : virt_to_phys(mac->fifo_tx[i + 1]);
ag7240_tx_own(mac->fifo_tx[i]);
}
if (ag7240_alloc_fifo(NO_OF_RX_FIFOS, mac->fifo_rx))
return 1;
for (i = 0; i < NO_OF_RX_FIFOS; i++) {
mac->fifo_rx[i]->next_desc = (i == NO_OF_RX_FIFOS - 1) ?
virt_to_phys(mac->fifo_rx[0]) : virt_to_phys(mac->fifo_rx[i + 1]);
}
return (1);
}
static void ag7240_halt(struct eth_device *dev)
{
ag7240_mac_t *mac = (ag7240_mac_t *)dev->priv;
ag7240_reg_wr(mac, AG7240_DMA_RX_CTRL, 0);
while (ag7240_reg_rd(mac, AG7240_DMA_RX_CTRL));
}
unsigned char *
ag7240_mac_addr_loc(void)
{
extern flash_info_t flash_info[];
#ifdef BOARDCAL
/*
** BOARDCAL environmental variable has the address of the cal sector
*/
return ((unsigned char *)BOARDCAL);
#else
/* MAC address is store in the 2nd 4k of last sector */
return ((unsigned char *)
(KSEG1ADDR(AR7240_SPI_BASE) + (4 * 1024) +
flash_info[0].size - (64 * 1024) /* sector_size */ ));
#endif
}
static void ag7240_get_ethaddr(struct eth_device *dev)
{
unsigned char *eeprom;
unsigned char *mac = dev->enetaddr;
#ifndef CONFIG_AR7240_EMU
eeprom = ag7240_mac_addr_loc();
if (strcmp(dev->name, "eth0") == 0) {
memcpy(mac, eeprom, 6);
} else if (strcmp(dev->name, "eth1") == 0) {
eeprom += 6;
memcpy(mac, eeprom, 6);
} else {
printf("%s: unknown ethernet device %s\n", __func__, dev->name);
return;
}
/* Use fixed address if the above address is invalid */
if (mac[0] != 0x00 || (mac[0] == 0xff && mac[5] == 0xff)) {
#else
if (1) {
#endif
mac[0] = 0x00;
mac[1] = 0x03;
mac[2] = 0x7f;
mac[3] = 0x09;
mac[4] = 0x0b;
mac[5] = 0xad;
printf("No valid address in Flash. Using fixed address\n");
} else {
printf("Fetching MAC Address from 0x%p\n", __func__, eeprom);
}
}
int ag7240_enet_initialize(bd_t * bis)
{
struct eth_device *dev[CFG_AG7240_NMACS];
u32 mask, mac_h, mac_l;
int i;
printf("ag7240_enet_initialize...\n");
if(is_ar933x() ) {
u32 rd = 0x0;
/*
* To get s26 out of reset, we have to...
* bit0~bit3: has to be deasserted
* bit4: has to be asserted
*/
rd = ar7240_reg_rd(AR7240_S26_CLK_CTRL_OFFSET) & ~(0x1f);
rd |= 0x10;
ar7240_reg_wr(AR7240_S26_CLK_CTRL_OFFSET, rd);
if(ar7240_reg_rd(AR7240_RESET)!=0)
ar7240_reg_wr(AR7240_RESET,0);
}
for (i = 0;i < CFG_AG7240_NMACS;i++) {
if ((dev[i] = (struct eth_device *) malloc(sizeof (struct eth_device))) == NULL) {
puts("malloc failed\n");
return 0;
}
if ((ag7240_macs[i] = (ag7240_mac_t *) malloc(sizeof (ag7240_mac_t))) == NULL) {
puts("malloc failed\n");
return 0;
}
memset(ag7240_macs[i], 0, sizeof(ag7240_macs[i]));
memset(dev[i], 0, sizeof(dev[i]));
sprintf(dev[i]->name, "eth%d", i);
ag7240_get_ethaddr(dev[i]);
ag7240_macs[i]->mac_unit = i;
ag7240_macs[i]->mac_base = i ? AR7240_GE1_BASE : AR7240_GE0_BASE ;
ag7240_macs[i]->dev = dev[i];
dev[i]->iobase = 0;
dev[i]->init = ag7240_clean_rx;
dev[i]->halt = ag7240_halt;
dev[i]->send = ag7240_send;
dev[i]->recv = ag7240_recv;
dev[i]->priv = (void *)ag7240_macs[i];
}
for (i = 0;i < CFG_AG7240_NMACS;i++) {
eth_register(dev[i]);
#ifdef CONFIG_MII
miiphy_register(dev[i]->name, ag7240_miiphy_read, ag7240_miiphy_write);
#endif
ag7240_reg_rmw_set(ag7240_macs[i], AG7240_MAC_CFG1, AG7240_MAC_CFG1_SOFT_RST
| AG7240_MAC_CFG1_RX_RST | AG7240_MAC_CFG1_TX_RST);
if(!i) {
mask = (AR7240_RESET_GE0_MAC | AR7240_RESET_GE0_PHY |
AR7240_RESET_GE1_MAC | AR7240_RESET_GE1_PHY);
if (is_ar7241() || is_ar7242() || is_wasp()) {
mask = mask | AR7240_RESET_GE0_MDIO | AR7240_RESET_GE1_MDIO;
printf(" wasp reset mask:%x \n",mask);
}
ar7240_reg_rmw_set(AR7240_RESET, mask);
if(!is_ar933x())
udelay(1000 * 100);
ar7240_reg_rmw_clear(AR7240_RESET, mask);
if(!is_ar933x())
udelay(1000 * 100);
if(!is_ar933x())
udelay(10 * 1000);
}
ag7240_hw_start(ag7240_macs[i]);
ag7240_setup_fifos(ag7240_macs[i]);
if(!is_ar933x())
udelay(100 * 1000);
{
unsigned char *mac = dev[i]->enetaddr;
printf("%s: %02x:%02x:%02x:%02x:%02x:%02x\n", dev[i]->name,
mac[0] & 0xff, mac[1] & 0xff, mac[2] & 0xff,
mac[3] & 0xff, mac[4] & 0xff, mac[5] & 0xff);
}
mac_l = (dev[i]->enetaddr[4] << 8) | (dev[i]->enetaddr[5]);
mac_h = (dev[i]->enetaddr[0] << 24) | (dev[i]->enetaddr[1] << 16) |
(dev[i]->enetaddr[2] << 8) | (dev[i]->enetaddr[3] << 0);
ag7240_reg_wr(ag7240_macs[i], AG7240_GE_MAC_ADDR1, mac_l);
ag7240_reg_wr(ag7240_macs[i], AG7240_GE_MAC_ADDR2, mac_h);
/* if using header for register configuration, we have to */
/* configure s26 register after frame transmission is enabled */
if (ag7240_macs[i]->mac_unit == 0) { /* WAN Phy */
#ifdef CONFIG_AR7242_S16_PHY
if (is_ar7242() || is_wasp()) {
athrs16_reg_init();
} else
#endif
{
#ifdef CFG_ATHRS26_PHY
athrs26_reg_init();
#endif
#ifdef CFG_ATHRS27_PHY
printf("s27 reg init \n");
athrs27_reg_init();
#endif
#ifdef CONFIG_F1E_PHY
printf("F1Phy reg init \n");
athr_reg_init();
#endif
}
} else {
#ifdef CFG_ATHRS26_PHY
printf("athrs26_reg_init_lan\n");
athrs26_reg_init_lan();
#endif
#ifdef CFG_ATHRS27_PHY
printf("s27 reg init lan \n");
athrs27_reg_init_lan();
#endif
}
ag7240_phy_setup(ag7240_macs[i]->mac_unit);
printf("%s up\n",dev[i]->name);
}
return 1;
}
#ifdef CONFIG_MII
uint16_t
ag7240_miiphy_read(char *devname, uint32_t phy_addr, uint8_t reg)
{
ag7240_mac_t *mac = ag7240_name2mac(devname);
uint16_t addr = (phy_addr << AG7240_ADDR_SHIFT) | reg, val;
volatile int rddata;
uint16_t ii = 0xFFFF;
/*
* Check for previous transactions are complete. Added to avoid
* race condition while running at higher frequencies.
*/
do
{
udelay(5);
rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;
}while(rddata && --ii);
if (ii == 0)
printf("ERROR:%s:%d transaction failed\n",__func__,__LINE__);
ag7240_reg_wr(mac, AG7240_MII_MGMT_CMD, 0x0);
ag7240_reg_wr(mac, AG7240_MII_MGMT_ADDRESS, addr);
ag7240_reg_wr(mac, AG7240_MII_MGMT_CMD, AG7240_MGMT_CMD_READ);
do
{
udelay(5);
rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;
}while(rddata && --ii);
if(ii==0)
printf("Error!!! Leave ag7240_miiphy_read without polling correct status!\n");
val = ag7240_reg_rd(mac, AG7240_MII_MGMT_STATUS);
ag7240_reg_wr(mac, AG7240_MII_MGMT_CMD, 0x0);
return val;
}
void
ag7240_miiphy_write(char *devname, uint32_t phy_addr, uint8_t reg, uint16_t data)
{
ag7240_mac_t *mac = ag7240_name2mac(devname);
uint16_t addr = (phy_addr << AG7240_ADDR_SHIFT) | reg;
volatile int rddata;
uint16_t ii = 0xFFFF;
/*
* Check for previous transactions are complete. Added to avoid
* race condition while running at higher frequencies.
*/
do
{
udelay(5);
rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;
}while(rddata && --ii);
if (ii == 0)
printf("ERROR:%s:%d transaction failed\n",__func__,__LINE__);
ag7240_reg_wr(mac, AG7240_MII_MGMT_ADDRESS, addr);
ag7240_reg_wr(mac, AG7240_MII_MGMT_CTRL, data);
do
{
rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;
}while(rddata && --ii);
if(ii==0)
printf("Error!!! Leave ag7240_miiphy_write without polling correct status!\n");
}
#endif /* CONFIG_MII */
@@ -0,0 +1,237 @@
#ifndef _AG7240_H
#define _AG7240_H
#include <linux/types.h>
/*
* h/w descriptor
*/
typedef struct {
uint32_t pkt_start_addr;
uint32_t is_empty : 1;
uint32_t res1 : 10;
uint32_t ftpp_override : 5;
uint32_t res2 : 4;
uint32_t pkt_size : 12;
uint32_t next_desc ;
}ag7240_desc_t;
#define NO_OF_TX_FIFOS 8
#define NO_OF_RX_FIFOS 8
typedef struct {
ag7240_desc_t *fifo_tx[NO_OF_TX_FIFOS];
ag7240_desc_t *fifo_rx[NO_OF_RX_FIFOS];
struct eth_device *dev;
u32 next_tx;
u32 next_rx;
u32 link;
u32 duplex;
u32 speed;
u32 mac_unit;
u32 mac_base;
}ag7240_mac_t;
#define ag7240_reg_wr(_mac, _x, _y) ar7240_reg_wr(((_x) + _mac->mac_base), (_y))
#define ag7240_reg_rd(_mac, _x) ar7240_reg_rd(((_x) + _mac->mac_base))
#define ag7240_reg_rmw_set(_mac, _x, _y) \
ar7240_reg_rmw_set(((_x) + _mac->mac_base ), (_y))
#define ag7240_reg_rmw_clear(_mac, _x, _y) \
ar7240_reg_rmw_clear(((_x) + _mac->mac_base), (_y))
#ifdef COMPRESSED_UBOOT
#define _1000BASET 1000
#define _100BASET 100
#define _10BASET 10
#endif /* #ifdef COMPRESSED_UBOOT */
/*
* spd is _1000BASET, _100BASET etc. defined in include/miiphy.h
*/
#define mii_reg(_mac) (AR7240_MII0_CTRL + ((_mac)->mac_unit * 4))
#define mii_if(_mac) (((_mac)->mac_unit == 0) ? mii0_if : mii1_if)
#define ag7240_set_mii_ctrl_speed(_mac, _spd) do { \
ar7240_reg_rmw_clear(mii_reg(_mac), (3 << 4)); \
ar7240_reg_rmw_set(mii_reg(_mac), ((_spd) << 4)); \
}while(0);
#if defined (CFG_MII0_GMII)
#define ag7240_get_mii_if() 0
#elif defined (CFG_MII0_MII)
#define ag7240_get_mii_if() 0
#elif defined (CFG_MII0_RGMII)
#define ag7240_get_mii_if() 0
#elif defined (CFG_MII0_RMII)
#define ag7240_get_mii_if() 0
#endif
#define MAX_WAIT 1000
/*
* Config/Mac Register definitions
*/
#define AG7240_MAC_CFG1 0x00
#define AG7240_MAC_CFG2 0x04
#define AG7240_MAC_IFCTL 0x38
/*
* fifo control registers
*/
#define AG7240_MAC_FIFO_CFG_0 0x48
#define AG7240_MAC_FIFO_CFG_1 0x4c
#define AG7240_MAC_FIFO_CFG_2 0x50
#define AG7240_MAC_FIFO_CFG_3 0x54
#define AG7240_MAC_FIFO_CFG_4 0x58
#define AG7240_MAC_FIFO_CFG_5 0x5c
#define AG7240_BYTE_PER_CLK_EN (1 << 19)
#define AG7240_MAC_FIFO_RAM_0 0x60
#define AG7240_MAC_FIFO_RAM_1 0x64
#define AG7240_MAC_FIFO_RAM_2 0x68
#define AG7240_MAC_FIFO_RAM_3 0x6c
#define AG7240_MAC_FIFO_RAM_4 0x70
#define AG7240_MAC_FIFO_RAM_5 0x74
#define AG7240_MAC_FIFO_RAM_6 0x78
#define AG7240_MAC_FIFO_RAM_7 0x7c
/*
* fields
*/
#define AG7240_MAC_CFG1_SOFT_RST (1 << 31)
#define AG7240_MAC_CFG1_RX_RST (1 << 19)
#define AG7240_MAC_CFG1_TX_RST (1 << 18)
#define AG7240_MAC_CFG1_LOOPBACK (1 << 8)
#define AG7240_MAC_CFG1_RX_EN (1 << 2)
#define AG7240_MAC_CFG1_TX_EN (1 << 0)
#define AG7240_MAC_CFG2_FDX (1 << 0)
#define AG7240_MAC_CFG2_PAD_CRC_EN (1 << 2)
#define AG7240_MAC_CFG2_LEN_CHECK (1 << 4)
#define AG7240_MAC_CFG2_HUGE_FRAME_EN (1 << 5)
#define AG7240_MAC_CFG2_IF_1000 (1 << 9)
#define AG7240_MAC_CFG2_IF_10_100 (1 << 8)
#define AG7240_MAC_IFCTL_SPEED (1 << 16)
/*
* DMA (tx/rx) register defines
*/
#define AG7240_DMA_TX_CTRL 0x180
#define AG7240_DMA_TX_DESC 0x184
#define AG7240_DMA_TX_STATUS 0x188
#define AG7240_DMA_RX_CTRL 0x18c
#define AG7240_DMA_RX_DESC 0x190
#define AG7240_DMA_RX_STATUS 0x194
#define AG7240_DMA_INTR_MASK 0x198
#define AG7240_DMA_INTR 0x19c
/*
* tx/rx ctrl and status bits
*/
#define AG7240_TXE (1 << 0)
#define AG7240_TX_STATUS_PKTCNT_SHIFT 16
#define AG7240_TX_STATUS_PKT_SENT 0x1
#define AG7240_TX_STATUS_URN 0x2
#define AG7240_TX_STATUS_BUS_ERROR 0x8
#define AG7240_RXE (1 << 0)
#define AG7240_RX_STATUS_PKTCNT_MASK 0xff0000
#define AG7240_RX_STATUS_PKT_RCVD (1 << 0)
#define AG7240_RX_STATUS_OVF (1 << 2)
#define AG7240_RX_STATUS_BUS_ERROR (1 << 3)
/*
* Int and int mask
*/
#define AG7240_INTR_TX (1 << 0)
#define AG7240_INTR_TX_URN (1 << 1)
#define AG7240_INTR_TX_BUS_ERROR (1 << 3)
#define AG7240_INTR_RX (1 << 4)
#define AG7240_INTR_RX_OVF (1 << 6)
#define AG7240_INTR_RX_BUS_ERROR (1 << 7)
/*
* MII registers
*/
#define AG7240_MAC_MII_MGMT_CFG 0x20
#define AG7240_MGMT_CFG_CLK_DIV_20 0x07
#define AG7240_MII_MGMT_CMD 0x24
#define AG7240_MGMT_CMD_READ 0x1
#define AG7240_MII_MGMT_ADDRESS 0x28
#define AG7240_ADDR_SHIFT 8
#define AG7240_MII_MGMT_CTRL 0x2c
#define AG7240_MII_MGMT_STATUS 0x30
#define AG7240_MII_MGMT_IND 0x34
#define AG7240_MGMT_IND_BUSY (1 << 0)
#define AG7240_MGMT_IND_INVALID (1 << 2)
#define AG7240_GE_MAC_ADDR1 0x40
#define AG7240_GE_MAC_ADDR2 0x44
/*
* Ethernet config registers
*/
#define AG7240_ETH_CFG 0x18070000
#define AG7240_ETH_CFG_RGMII_GE0 (1<<0)
#define AG7240_ETH_CFG_MII_GE0 (1<<1)
#define AG7240_ETH_CFG_GMII_GE0 (1<<2)
#define AG7240_ETH_CFG_MII_GE0_MASTER (1<<3)
#define AG7240_ETH_CFG_MII_GE0_SLAVE (1<<4)
#define AG7240_ETH_CFG_GE0_ERR_EN (1<<5)
#define AG7240_ETH_CFG_SW_ONLY_MODE (1<<6)
#define AG7240_ETH_CFG_SW_PHY_SWAP (1<<7)
#define AG7240_ETH_CFG_SW_PHY_ADDR_SWAP (1<<8)
#define AG7240_ETH_SWITCH_CLK_SPARE 0x18050024
/*
* * ownership of descriptors between DMA and cpu
* */
#define ag7240_rx_owned_by_dma(_ds) ((_ds)->is_empty == 1)
#define ag7240_rx_give_to_dma(_ds) ((_ds)->is_empty = 1)
#define ag7240_tx_owned_by_dma(_ds) ((_ds)->is_empty == 0)
#define ag7240_tx_give_to_dma(_ds) ((_ds)->is_empty = 0)
#define ag7240_tx_own(_ds) ((_ds)->is_empty = 1)
/*
* link settings
*/
#define ag7240_set_mac_duplex(_mac, _fdx) do { \
if ((_fdx)) \
ag7240_reg_rmw_set(_mac, AG7240_MAC_CFG2, AG7240_MAC_CFG2_FDX) \
else \
ag7240_reg_rmw_clear(_mac, AG7240_MAC_CFG2, AG7240_MAC_CFG2_FDX) \
}while(0)
#define ag7240_set_mac_if(_mac, _isXGMII) do { \
ag7240_reg_rmw_clear(_mac, AG7240_MAC_CFG2, AG7240_MAC_CFG2_IF_1000| \
AG7240_MAC_CFG2_IF_10_100); \
if ((_isXGMII)) { \
ag7240_reg_rmw_set(_mac, AG7240_MAC_CFG2, AG7240_MAC_CFG2_IF_1000) \
ag7240_reg_rmw_set(_mac, AG7240_MAC_FIFO_CFG_5, AG7240_BYTE_PER_CLK_EN);\
} \
else { \
ag7240_reg_rmw_set(_mac, AG7240_MAC_CFG2, AG7240_MAC_CFG2_IF_10_100)\
ag7240_reg_rmw_clear(_mac, AG7240_MAC_FIFO_CFG_5, AG7240_BYTE_PER_CLK_EN);\
} \
}while(0)
#define ag7240_set_mac_speed(_mac, _is100) do { \
if ((_is100)) \
ag7240_reg_rmw_set(_mac, AG7240_MAC_IFCTL, AG7240_MAC_IFCTL_SPEED) \
else \
ag7240_reg_rmw_clear(_mac, AG7240_MAC_IFCTL, AG7240_MAC_IFCTL_SPEED)\
}while(0)
#endif
@@ -0,0 +1,69 @@
#ifndef _AG7240_PHY_H
#define _AG7240_PHY_H
static inline void ag7240_phy_setup(int unit)
{
#ifdef CONFIG_AR7242_S16_PHY
if ((is_ar7242() || is_wasp()) && (unit==0)) {
athrs16_phy_setup(unit);
} else
#endif
{
athrs26_phy_setup(unit);
#ifdef CONFIG_F1E_PHY
athr_phy_setup(unit);
#endif
}
}
static inline void ag7240_phy_link(int unit, int *link)
{
#ifdef CONFIG_AR7242_S16_PHY
if ((is_ar7242() || is_wasp()) && (unit==0)) {
*link = athrs16_phy_is_up(unit);
} else
#endif
{
#ifdef CFG_ATHRS27_PHY
*link = athrs27_phy_is_up(unit);
#endif
#ifdef CFG_ATHRS26_PHY
*link = athrs26_phy_is_up(unit);
#endif
#ifdef CONFIG_F1E_PHY
*link = athr_phy_is_up(unit);
#endif
}
}
static inline void ag7240_phy_duplex(int unit, int *duplex)
{
#ifdef CONFIG_AR7242_S16_PHY
if ((is_ar7242() || is_wasp()) && (unit==0)) {
*duplex = athrs16_phy_is_fdx(unit);
} else
#endif
{
*duplex = athrs26_phy_is_fdx(unit);
#ifdef CONFIG_F1E_PHY
*duplex = athr_phy_is_fdx(unit);
#endif
}
}
static inline void ag7240_phy_speed(int unit, int *speed)
{
#ifdef CONFIG_AR7242_S16_PHY
if ((is_ar7242() || is_wasp()) && (unit==0)) {
*speed = athrs16_phy_speed(unit);
} else
#endif
{
*speed = athrs26_phy_speed(unit);
#ifdef CONFIG_F1E_PHY
*speed = athr_phy_speed(unit);
#endif
}
}
#endif /*_AG7240_PHY_H*/
@@ -0,0 +1,910 @@
#include <common.h>
#include <malloc.h>
#include <net.h>
#include <command.h>
#include <asm/io.h>
#include <asm/addrspace.h>
#include <asm/types.h>
#ifdef CONFIG_ATH_NAND_BR
#include <nand.h>
#endif
#include "ar7240_soc.h"
#include "ag934x.h"
#include <miiphy.h>
#undef AG934X_ETH_DEBUG
#define ag7240_unit2mac(_unit) ag7240_macs[(_unit)]
#if defined(CONFIG_BOARD_PLA4231)
#define ag7240_name2mac(name) strcmp(name,"eth0") ? ag7240_unit2mac(0) : ag7240_unit2mac(1)
#else
#define ag7240_name2mac(name) strcmp(name,"eth0") ? ag7240_unit2mac(1) : ag7240_unit2mac(0)
#endif
uint16_t ag7240_miiphy_read(char *devname, uint32_t phaddr,
uint8_t reg);
void ag7240_miiphy_write(char *devname, uint32_t phaddr,
uint8_t reg, uint16_t data);
ag7240_mac_t *ag7240_macs[CFG_AG7240_NMACS];
extern void ar7240_sys_frequency(u32 *cpu_freq, u32 *ddr_freq, u32 *ahb_freq);
#ifdef CFG_ATHRS26_PHY
extern int athrs26_phy_setup(int unit);
extern int athrs26_phy_is_up(int unit);
extern int athrs26_phy_is_fdx(int unit);
extern int athrs26_phy_speed(int unit);
extern void athrs26_reg_init(void);
extern void athrs26_reg_init_lan(void);
extern int athrs26_mdc_check(void);
#endif
#ifdef CFG_ATHRS27_PHY
extern int athrs27_phy_setup(int unit);
extern int athrs27_phy_is_up(int unit);
extern int athrs27_phy_is_fdx(int unit,int phyUnit);
extern int athrs27_phy_speed(int unit,int phyUnit);
extern void athrs27_reg_init(void);
extern void athrs27_reg_init_lan(void);
extern int athrs27_mdc_check(void);
#endif
#if defined(CONFIG_F1E_PHY) || defined(CONFIG_F2E_PHY)
extern int athr_phy_setup(int unit);
extern int athr_phy_is_up(int unit);
extern int athr_phy_is_fdx(int unit);
extern int athr_phy_speed(int unit);
extern void athr_reg_init(void);
#endif
#ifdef CONFIG_VIR_PHY
extern int athr_vir_phy_setup(int unit);
extern int athr_vir_phy_is_up(int unit);
extern int athr_vir_phy_is_fdx(int unit);
extern int athr_vir_phy_speed(int unit);
extern void athr_vir_reg_init(void);
#endif
#include "ag934x_phy.h"
#ifdef CONFIG_ATH_NAND_BR
#define ATH_ETH_MAC_READ_SIZE 4096
extern unsigned long long
ath_nand_get_cal_offset(const char *ba);
#endif
static int
ag7240_send(struct eth_device *dev, volatile void *packet, int length)
{
int i;
ag7240_mac_t *mac = (ag7240_mac_t *)dev->priv;
ag7240_desc_t *f = mac->fifo_tx[mac->next_tx];
f->pkt_size = length;
f->res1 = 0;
f->pkt_start_addr = virt_to_phys(packet);
ag7240_tx_give_to_dma(f);
flush_cache((u32) packet, length);
ag7240_reg_wr(mac, AG7240_DMA_TX_DESC, virt_to_phys(f));
ag7240_reg_wr(mac, AG7240_DMA_TX_CTRL, AG7240_TXE);
for (i = 0; i < MAX_WAIT; i++) {
udelay(10);
if (!ag7240_tx_owned_by_dma(f))
break;
}
if (i == MAX_WAIT)
printf("Tx Timed out\n");
f->pkt_start_addr = 0;
f->pkt_size = 0;
if (++mac->next_tx >= NO_OF_TX_FIFOS)
mac->next_tx = 0;
return(0);
}
static int ag7240_recv(struct eth_device *dev)
{
int length;
ag7240_desc_t *f;
ag7240_mac_t *mac;
mac = (ag7240_mac_t *)dev->priv;
for (;;) {
f = mac->fifo_rx[mac->next_rx];
if (ag7240_rx_owned_by_dma(f))
break;
length = f->pkt_size;
NetReceive(NetRxPackets[mac->next_rx] , length - 4);
flush_cache((u32) NetRxPackets[mac->next_rx] , PKTSIZE_ALIGN);
ag7240_rx_give_to_dma(f);
if (++mac->next_rx >= NO_OF_RX_FIFOS)
mac->next_rx = 0;
}
if (!(ag7240_reg_rd(mac, AG7240_DMA_RX_CTRL))) {
ag7240_reg_wr(mac, AG7240_DMA_RX_DESC, virt_to_phys(f));
ag7240_reg_wr(mac, AG7240_DMA_RX_CTRL, 1);
}
return(0);
}
void ag7240_mii_setup(ag7240_mac_t *mac)
{
u32 mgmt_cfg_val;
u32 cpu_freq,ddr_freq,ahb_freq;
u32 check_cnt; //,revid_val;
if ((ar7240_reg_rd(WASP_BOOTSTRAP_REG) & WASP_REF_CLK_25) == 0) {
#ifndef CFG_DUAL_PHY_SUPPORT
ar7240_reg_wr(AR934X_SWITCH_CLOCK_SPARE, 0x271);
#endif
} else {
ar7240_reg_wr(AR934X_SWITCH_CLOCK_SPARE, 0x570);
}
#if defined(CONFIG_AR7242_S16_PHY) || defined(CONFIG_ATHRS17_PHY)
if (is_wasp() && mac->mac_unit == 0) {
#ifdef CONFIG_AR7242_S16_PHY
//printf("WASP ----> S16 PHY *\n");
puts("(S16*) ");
#else
//printf("WASP ----> S17 PHY *\n");
puts("(S17*) ");
#endif
mgmt_cfg_val = 4;
if (mac->mac_unit == 0)
ar7240_reg_wr(AG7240_ETH_CFG, AG7240_ETH_CFG_RGMII_GE0);
udelay(1000);
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
return;
}
#endif
#ifdef CFG_ATHRS27_PHY
if (is_wasp()) {
// printf("WASP ----> S27 PHY \n");
puts("(S27) ");
mgmt_cfg_val = 2;
ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
return;
}
#endif
#ifdef CONFIG_F2E_PHY
if (is_wasp()) {
//printf("WASP ----> F2 PHY *\n");
puts("(F2*) ");
ar7240_reg_wr(AG7240_ETH_CFG, (AG7240_ETH_CFG_RMII_MASTER_MODE | AG7240_ETH_CFG_RMII_GE0
| AG7240_ETH_CFG_RMII_HISPD_GE0));
mgmt_cfg_val = 6;
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
return;
}
#endif
#if defined(CONFIG_F1E_PHY) || defined(CONFIG_VIR_PHY)
if (is_wasp()) {
#ifdef CONFIG_VIR_PHY
//printf("WASP ----> VIR PHY *\n");
puts("(VIR) ");
#else
//printf("WASP ----> F1 PHY *\n");
puts("(F1) ");
#endif
if (mac->mac_unit == 0)
ar7240_reg_wr(AG7240_ETH_CFG, AG7240_ETH_CFG_RGMII_GE0);
mgmt_cfg_val = 6;
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
return;
}
#endif
if ((ar7240_reg_rd(AR7240_REV_ID) & AR7240_REV_ID_MASK) == AR7240_REV_1_2) {
mgmt_cfg_val = 0x2;
if (mac->mac_unit == 0) {
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
}
} else {
ar7240_sys_frequency(&cpu_freq, &ddr_freq, &ahb_freq);
switch (ahb_freq/1000000) {
case 150:
mgmt_cfg_val = 0x7;
break;
case 175:
mgmt_cfg_val = 0x5;
break;
case 200:
mgmt_cfg_val = 0x4;
break;
case 210:
mgmt_cfg_val = 0x9;
break;
case 220:
mgmt_cfg_val = 0x9;
break;
default:
mgmt_cfg_val = 0x7;
}
if ((is_ar7241() || is_ar7242())) {
/* External MII mode */
if (mac->mac_unit == 0 && is_ar7242()) {
mgmt_cfg_val = 0x6;
ar7240_reg_rmw_set(AG7240_ETH_CFG, AG7240_ETH_CFG_RGMII_GE0);
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
}
/* Virian */
mgmt_cfg_val = 0x4;
ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
printf("Virian MDC CFG Value ==> %x\n",mgmt_cfg_val);
} else if (is_ar933x()) {
//GE0 receives Rx/Tx clock, and use S26 phy
ar7240_reg_rmw_set(AG7240_ETH_CFG, AG7240_ETH_CFG_MII_GE0_SLAVE);
mgmt_cfg_val = 0xF;
if (mac->mac_unit == 1) {
check_cnt = 0;
while (check_cnt++ < 10) {
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
#ifdef CFG_ATHRS26_PHY
if (athrs26_mdc_check() == 0)
break;
#endif
}
if (check_cnt == 11)
printf("%s: MDC check failed\n", __func__);
}
} else { /* Python 1.0 & 1.1 */
if (mac->mac_unit == 0) {
check_cnt = 0;
while (check_cnt++ < 10) {
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
#ifdef CFG_ATHRS26_PHY
if (athrs26_mdc_check() == 0)
break;
#endif
}
if (check_cnt == 11)
printf("%s: MDC check failed\n", __func__);
}
}
}
}
static void ag7240_hw_start(ag7240_mac_t *mac)
{
if (mac->mac_unit) {
ag7240_reg_wr(mac, AG7240_MAC_CFG1, (AG7240_MAC_CFG1_RX_EN |
AG7240_MAC_CFG1_TX_EN));
ag7240_reg_rmw_set(mac, AG7240_MAC_CFG2, (AG7240_MAC_CFG2_PAD_CRC_EN |
AG7240_MAC_CFG2_LEN_CHECK | AG7240_MAC_CFG2_IF_1000));
} else {
ag7240_reg_rmw_set(mac, AG7240_MAC_CFG2, (AG7240_MAC_CFG2_PAD_CRC_EN |
AG7240_MAC_CFG2_LEN_CHECK | AG7240_MAC_CFG2_IF_10_100));
}
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_0, 0x1f00);
ag7240_mii_setup(mac);
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_1, 0x10ffff);
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_2, 0xAAA0555);
ag7240_reg_rmw_set(mac, AG7240_MAC_FIFO_CFG_4, 0x3ffff);
/*
* Setting Drop CRC Errors, Pause Frames,Length Error frames
* and Multi/Broad cast frames.
*/
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_5, 0x7eccf);
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_3, 0x1f00140);
#ifdef AG934X_ETH_DEBUG
printf(": cfg1 %#x cfg2 %#x\n", ag7240_reg_rd(mac, AG7240_MAC_CFG1),
ag7240_reg_rd(mac, AG7240_MAC_CFG2));
#endif
}
static int ag7240_check_link(ag7240_mac_t *mac)
{
u32 link, duplex, speed;//, fdx;
ag7240_phy_link(mac->mac_unit, &link);
ag7240_phy_duplex(mac->mac_unit, &duplex);
ag7240_phy_speed(mac->mac_unit, &speed);
mac->link = link;
#ifdef SUPPORT_PLC
if (strcmp(mac->dev->name, "eth0") == 0) {
printf("ag7240_check_link: %s link forced down\n",mac->dev->name);
return 0;
}
#endif
if (!mac->link) {
printf("%s link down\n",mac->dev->name);
return 0;
}
switch (speed) {
case _1000BASET:
ag7240_set_mac_if(mac, 1);
ag7240_reg_rmw_set(mac, AG7240_MAC_FIFO_CFG_5, (1 << 19));
if (is_ar7242() && (mac->mac_unit == 0)) {
ar7240_reg_wr(AR7242_ETH_XMII_CONFIG,0x1c000000);
}
#ifdef CONFIG_F1E_PHY
if (is_wasp() && (mac->mac_unit == 0)) {
ar7240_reg_wr(AR7242_ETH_XMII_CONFIG,0x0e000000);
}
#elif CONFIG_VIR_PHY
if (is_wasp() && (mac->mac_unit == 0)) {
ar7240_reg_wr(AR7242_ETH_XMII_CONFIG,0x82000000);
ar7240_reg_wr(AG7240_ETH_CFG,0x000c0001);
}
#else
if (is_wasp() && (mac->mac_unit == 0) && !is_f2e()) {
ar7240_reg_wr(AR7242_ETH_XMII_CONFIG,0x06000000);
}
#endif
if (is_wasp() && mac->mac_unit == 0 && is_f1e() ) {
ar7240_reg_rmw_set(AG7240_ETH_CFG,AG7240_ETH_CFG_RXD_DELAY);
ar7240_reg_rmw_set(AG7240_ETH_CFG,AG7240_ETH_CFG_RDV_DELAY);
}
break;
case _100BASET:
ag7240_set_mac_if(mac, 0);
ag7240_set_mac_speed(mac, 1);
ag7240_reg_rmw_clear(mac, AG7240_MAC_FIFO_CFG_5, (1 << 19));
if ((is_ar7242() || is_wasp()) && (mac->mac_unit == 0) && !is_f2e())
ar7240_reg_wr(AR7242_ETH_XMII_CONFIG,0x0101);
if (is_wasp() && mac->mac_unit == 0 && is_f1e()) {
ar7240_reg_rmw_clear(AG7240_ETH_CFG,AG7240_ETH_CFG_RXD_DELAY);
ar7240_reg_rmw_clear(AG7240_ETH_CFG,AG7240_ETH_CFG_RDV_DELAY);
}
break;
case _10BASET:
ag7240_set_mac_if(mac, 0);
ag7240_set_mac_speed(mac, 0);
ag7240_reg_rmw_clear(mac, AG7240_MAC_FIFO_CFG_5, (1 << 19));
if ((is_ar7242() || is_wasp()) && (mac->mac_unit == 0) && !is_f2e())
ar7240_reg_wr(AR7242_ETH_XMII_CONFIG,0x1616);
if (is_wasp() && mac->mac_unit == 0 && is_f1e()) {
ar7240_reg_rmw_clear(AG7240_ETH_CFG,AG7240_ETH_CFG_RXD_DELAY);
ar7240_reg_rmw_clear(AG7240_ETH_CFG,AG7240_ETH_CFG_RDV_DELAY);
}
if (is_f2e()) {
ar7240_reg_rmw_clear(AG7240_ETH_CFG, AG7240_ETH_CFG_RMII_HISPD_GE0);
}
break;
default:
printf("Invalid speed detected\n");
return 0;
}
if (mac->link && (duplex == mac->duplex) && (speed == mac->speed))
return 1;
mac->duplex = duplex;
mac->speed = speed;
printf("dup %d speed %d\n", duplex, speed);
ag7240_set_mac_duplex(mac,duplex);
return 1;
}
/*
* For every command we re-setup the ring and start with clean h/w rx state
*/
static int ag7240_clean_rx(struct eth_device *dev, bd_t * bd)
{
int i;
ag7240_desc_t *fr;
ag7240_mac_t *mac = (ag7240_mac_t*)dev->priv;
if (!ag7240_check_link(mac))
return 0;
mac->next_rx = 0;
/**
* @ when executing TFTP transfers at -10C
* @ time taken for auto negotiation and link to settled down
* @ is quite high. provide 3 Sec delay for s17 link to settle
* @ down. Works fine at room temparature, 0C -3C
@ Suggested by systems team.
*/
#ifdef CONFIG_ATHRS17_PHY
udelay(1000 * 3000);
#endif
ag7240_reg_wr(mac, AG7240_MAC_CFG1, (AG7240_MAC_CFG1_RX_EN |
AG7240_MAC_CFG1_TX_EN));
for (i = 0; i < NO_OF_RX_FIFOS; i++) {
fr = mac->fifo_rx[i];
fr->pkt_start_addr = virt_to_phys(NetRxPackets[i]);
flush_cache((u32) NetRxPackets[i], PKTSIZE_ALIGN);
ag7240_rx_give_to_dma(fr);
}
ag7240_reg_wr(mac, AG7240_DMA_RX_DESC, virt_to_phys(mac->fifo_rx[0]));
ag7240_reg_wr(mac, AG7240_DMA_RX_CTRL, AG7240_RXE); /* rx start */
udelay(1000 * 1000);
return 1;
}
static int ag7240_alloc_fifo(int ndesc, ag7240_desc_t ** fifo)
{
int i;
u32 size;
uchar *p = NULL;
size = sizeof(ag7240_desc_t) * ndesc;
size += CONFIG_SYS_CACHELINE_SIZE - 1;
if ((p = malloc(size)) == NULL) {
printf("Cant allocate fifos\n");
return -1;
}
p = (uchar *) (((u32) p + CONFIG_SYS_CACHELINE_SIZE - 1) &
~(CONFIG_SYS_CACHELINE_SIZE - 1));
p = (uchar *)UNCACHED_SDRAM(p);
for (i = 0; i < ndesc; i++)
fifo[i] = (ag7240_desc_t *) p + i;
return 0;
}
static int ag7240_setup_fifos(ag7240_mac_t *mac)
{
int i;
if (ag7240_alloc_fifo(NO_OF_TX_FIFOS, mac->fifo_tx))
return 1;
for (i = 0; i < NO_OF_TX_FIFOS; i++) {
mac->fifo_tx[i]->next_desc = (i == NO_OF_TX_FIFOS - 1) ?
virt_to_phys(mac->fifo_tx[0]) : virt_to_phys(mac->fifo_tx[i + 1]);
ag7240_tx_own(mac->fifo_tx[i]);
}
if (ag7240_alloc_fifo(NO_OF_RX_FIFOS, mac->fifo_rx))
return 1;
for (i = 0; i < NO_OF_RX_FIFOS; i++) {
mac->fifo_rx[i]->next_desc = (i == NO_OF_RX_FIFOS - 1) ?
virt_to_phys(mac->fifo_rx[0]) : virt_to_phys(mac->fifo_rx[i + 1]);
}
return(1);
}
static void ag7240_halt(struct eth_device *dev)
{
ag7240_mac_t *mac = (ag7240_mac_t *)dev->priv;
ag7240_reg_wr(mac, AG7240_DMA_RX_CTRL, 0);
while (ag7240_reg_rd(mac, AG7240_DMA_RX_CTRL));
}
#if 0
#ifdef CONFIG_ATH_NAND_BR
unsigned char *
ath_eth_mac_addr(unsigned char *sectorBuff)
{
ulong off, size;
nand_info_t *nand;
unsigned char ret;
/*
* caldata partition is of 128k
*
*/
nand = &nand_info[nand_curr_device];
size = ATH_ETH_MAC_READ_SIZE; /* To read 4k setting size as 4k */
/*
* Get the Offset of Caldata partition
*/
off = ath_nand_get_cal_offset(getenv("bootargs"));
if (off == ATH_CAL_OFF_INVAL) {
printf("Invalid CAL offset \n");
return NULL;
}
/*
* Get the values from flash, and program into the MAC address
* registers
*/
ret = nand_read(nand, (loff_t)off, &size, (u_char *)sectorBuff);
printf(" %d bytes %s: %s\n", size,
"read", ret ? "ERROR" : "OK");
if (ret != 0 ) {
return NULL;
}
return sectorBuff;
}
#else /* CONFIG_ATH_NAND_BR */
unsigned char *
ag7240_mac_addr_loc(void)
{
extern flash_info_t flash_info[] __maybe_unused;
#ifdef BOARDCAL
/*
** BOARDCAL environmental variable has the address of the cal sector
*/
return((unsigned char *)BOARDCAL);
#else
/* MAC address is store in the 2nd 4k of last sector */
return((unsigned char *)
(KSEG1ADDR(AR7240_SPI_BASE) + (4 * 1024) +
flash_info[0].size - (64 * 1024) /* sector_size */ ));
#endif
}
#endif /* CONFIG_ATH_NAND_BR */
#endif
#if 0 /* remove it, we get MAC address from uboot environment */
static void ag7240_get_ethaddr(struct eth_device *dev)
{
unsigned char *eeprom;
unsigned char *mac = dev->enetaddr;
#ifndef CONFIG_AR7240_EMU
#ifdef CONFIG_ATH_NAND_BR
unsigned char sectorBuff[ATH_ETH_MAC_READ_SIZE];
eeprom = ath_eth_mac_addr(sectorBuff);
if (eeprom == NULL) {
/* mac address will be set to default mac address */
mac[0] = 0xff;
} else {
#else /* CONFIG_ATH_NAND_BR */
eeprom = ag7240_mac_addr_loc();
#endif /* CONFIG_ATH_NAND_BR */
if (strcmp(dev->name, "eth0") == 0) {
memcpy(mac, eeprom, 6);
} else if (strcmp(dev->name, "eth1") == 0) {
eeprom += 6;
memcpy(mac, eeprom, 6);
} else {
printf("%s: unknown ethernet device %s\n", __func__, dev->name);
return;
}
#ifdef CONFIG_ATH_NAND_BR
}
#endif /* CONFIG_ATH_NAND_BR */
/* Use fixed address if the above address is invalid */
if (mac[0] != 0x00 || (mac[0] == 0xff && mac[5] == 0xff)) {
#else
if (1) {
#endif
mac[0] = 0x00;
mac[1] = 0x03;
mac[2] = 0x7f;
mac[3] = 0x09;
mac[4] = 0x0b;
mac[5] = 0xad;
printf("No valid address in Flash. Using fixed address\n");
} else {
printf("Fetching MAC Address from 0x%p\n", eeprom);
}
}
#endif
int ag7240_enet_initialize(bd_t * bis)
{
struct eth_device *dev[CFG_AG7240_NMACS];
u32 mask, mac_h, mac_l;
int i;
//printf("ag934x_enet_initialize...\n");
if (is_ar933x() && (ar7240_reg_rd(AR7240_RESET)!=0))
ar7240_reg_wr(AR7240_RESET,0);
if (is_ar933x()) //Turn on LED
ar7240_reg_wr(AR7240_GPIO_BASE + 0x28 , ar7240_reg_rd(AR7240_GPIO_BASE + 0x28) | (0xF8));
for (i = 0;i < CFG_AG7240_NMACS;i++) {
if ((dev[i] = (struct eth_device *) malloc(sizeof (struct eth_device))) == NULL) {
puts("malloc failed\n");
return 0;
}
if ((ag7240_macs[i] = (ag7240_mac_t *) malloc(sizeof (ag7240_mac_t))) == NULL) {
puts("malloc failed\n");
return 0;
}
memset(ag7240_macs[i], 0, sizeof(ag7240_macs[i]));
memset(dev[i], 0, sizeof(dev[i]));
sprintf(dev[i]->name, "eth%d", i);
#if 0 /* for zyxel, we get MAC address from u-boot environment */
ag7240_get_ethaddr(dev[i]);
#else
#if defined(CONFIG_BOARD_PLA4231)
eth_getenv_enetaddr_by_index(CFG_AG7240_NMACS-i-1, dev[i]->enetaddr);
#elif defined(CONFIG_BOARD_AP123)
eth_getenv_enetaddr_by_index(i, dev[i]->enetaddr);
#else
#error "Unknown board type, how to get MAC address?"
#endif
#endif
ag7240_macs[i]->mac_unit = i;
ag7240_macs[i]->mac_base = i ? AR7240_GE1_BASE : AR7240_GE0_BASE ;
ag7240_macs[i]->dev = dev[i];
dev[i]->iobase = 0;
dev[i]->init = ag7240_clean_rx;
dev[i]->halt = ag7240_halt;
dev[i]->send = ag7240_send;
dev[i]->recv = ag7240_recv;
dev[i]->priv = (void *)ag7240_macs[i];
}
for (i = 0;i < CFG_AG7240_NMACS;i++) {
#ifndef CONFIG_BOARD_PLA4231
eth_register(dev[i]);
#ifdef CONFIG_MII
miiphy_register(dev[i]->name, ag7240_miiphy_read, ag7240_miiphy_write);
#endif
#endif
ag7240_reg_rmw_set(ag7240_macs[i], AG7240_MAC_CFG1, AG7240_MAC_CFG1_SOFT_RST
| AG7240_MAC_CFG1_RX_RST | AG7240_MAC_CFG1_TX_RST);
if (!i) {
#ifdef CONFIG_ATH_NAND_BR
mask = (AR7240_RESET_GE0_MAC | AR7240_RESET_GE0_PHY |
AR7240_RESET_GE1_MAC);
#else
mask = (AR7240_RESET_GE0_MAC | AR7240_RESET_GE0_PHY |
AR7240_RESET_GE1_MAC | AR7240_RESET_GE1_PHY);
#endif
if (is_ar7241() || is_ar7242() || is_wasp())
mask = mask | AR7240_RESET_GE0_MDIO | AR7240_RESET_GE1_MDIO;
//printf(" wasp reset mask:%x \n",mask);
ar7240_reg_rmw_set(AR7240_RESET, mask);
udelay(1000 * 100);
ar7240_reg_rmw_clear(AR7240_RESET, mask);
udelay(1000 * 100);
udelay(10 * 1000);
}
ag7240_hw_start(ag7240_macs[i]);
ag7240_setup_fifos(ag7240_macs[i]);
udelay(100 * 1000);
#ifdef AG934X_ETH_DEBUG
{
unsigned char *mac = dev[i]->enetaddr;
printf("%s: %02x:%02x:%02x:%02x:%02x:%02x\n", dev[i]->name,
mac[0] & 0xff, mac[1] & 0xff, mac[2] & 0xff,
mac[3] & 0xff, mac[4] & 0xff, mac[5] & 0xff);
}
#endif
mac_l = (dev[i]->enetaddr[4] << 8) | (dev[i]->enetaddr[5]);
mac_h = (dev[i]->enetaddr[0] << 24) | (dev[i]->enetaddr[1] << 16) |
(dev[i]->enetaddr[2] << 8) | (dev[i]->enetaddr[3] << 0);
ag7240_reg_wr(ag7240_macs[i], AG7240_GE_MAC_ADDR1, mac_l);
ag7240_reg_wr(ag7240_macs[i], AG7240_GE_MAC_ADDR2, mac_h);
/* if using header for register configuration, we have to */
/* configure s26 register after frame transmission is enabled */
if (ag7240_macs[i]->mac_unit == 0) { /* WAN Phy */
#ifdef CONFIG_AR7242_S16_PHY
if (is_ar7242() || is_wasp()) {
athrs16_reg_init();
} else
#endif
{
#ifdef CONFIG_ATHRS17_PHY
athrs17_reg_init();
#endif
#ifdef CFG_ATHRS26_PHY
athrs26_reg_init();
#endif
#ifdef CFG_ATHRS27_PHY
//printf("s27 reg init \n");
athrs27_reg_init();
#endif
#ifdef CONFIG_F1E_PHY
printf("F1Phy reg init \n");
athr_reg_init();
#endif
#ifdef CONFIG_VIR_PHY
printf("VIRPhy reg init \n");
athr_vir_reg_init();
#endif
#ifdef CONFIG_F2E_PHY
printf("F2Phy reg init \n");
athr_reg_init();
#endif
}
} else {
#ifdef CFG_ATHRS26_PHY
athrs26_reg_init_lan();
#endif
#ifdef CFG_ATHRS27_PHY
//printf("s27 reg init lan \n");
athrs27_reg_init_lan();
#endif
}
ag7240_phy_setup(ag7240_macs[i]->mac_unit);
//printf("%s up\n",dev[i]->name);
}
#if defined(CONFIG_BOARD_PLA4231)
strcpy(dev[1]->name, "eth0");
strcpy(dev[0]->name, "eth1");
/* for loader, we only need one ethernet interface is enough */
eth_register(dev[1]);
#ifdef CONFIG_MII
miiphy_register(dev[1]->name, ag7240_miiphy_read, ag7240_miiphy_write);
#endif
/* delay 1sec, workaround for multiboot & avoid core dump issue!
* 1. To ensure PHY link-up because eth_init()/ag7240_clean_rx() will check link status,
* if link-down, it will disable RX.
* 2. kernel booting will be core dump if there have traffic on Ethernet interface.
* So, need to waiting for ethernet controller more stable?!
*/
udelay(1000000);
/*
* The Default setting of driver will ignore multicast patcket,
* so need to change setting for zloader to using multiboot functionality.
*/
#ifdef CONFIG_ZYXEL_ZLOADER
#if defined(CONFIG_BOARD_PLA4231)
ag7240_reg_rmw_set(ag7240_macs[1], AG7240_ETH_CFG5, (1<<8));
#else
#error "Which GMAC(0 or 1) need to pass multicase packet?"
#endif
#endif
#endif
return 1;
}
#if defined(CONFIG_MII) || defined(CONFIG_ZYXEL_ZLOADER)
uint16_t
ag7240_miiphy_read(char *devname, uint32_t phy_addr, uint8_t reg)
{
ag7240_mac_t *mac = ag7240_name2mac(devname);
uint16_t addr = (phy_addr << AG7240_ADDR_SHIFT) | reg, val;
volatile int rddata;
uint16_t ii = 0xFFFF;
/*
* Check for previous transactions are complete. Added to avoid
* race condition while running at higher frequencies.
*/
do {
udelay(5);
rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;
}while (rddata && --ii);
if (ii == 0)
printf("ERROR:%s:%d transaction failed\n",__func__,__LINE__);
ag7240_reg_wr(mac, AG7240_MII_MGMT_CMD, 0x0);
ag7240_reg_wr(mac, AG7240_MII_MGMT_ADDRESS, addr);
ag7240_reg_wr(mac, AG7240_MII_MGMT_CMD, AG7240_MGMT_CMD_READ);
do {
udelay(5);
rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;
}while (rddata && --ii);
if (ii==0)
printf("Error!!! Leave ag7240_miiphy_read without polling correct status!\n");
val = ag7240_reg_rd(mac, AG7240_MII_MGMT_STATUS);
ag7240_reg_wr(mac, AG7240_MII_MGMT_CMD, 0x0);
return val;
}
void
ag7240_miiphy_write(char *devname, uint32_t phy_addr, uint8_t reg, uint16_t data)
{
ag7240_mac_t *mac = ag7240_name2mac(devname);
uint16_t addr = (phy_addr << AG7240_ADDR_SHIFT) | reg;
volatile int rddata;
uint16_t ii = 0xFFFF;
/*
* Check for previous transactions are complete. Added to avoid
* race condition while running at higher frequencies.
*/
do {
udelay(5);
rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;
}while (rddata && --ii);
if (ii == 0)
printf("ERROR:%s:%d transaction failed\n",__func__,__LINE__);
ag7240_reg_wr(mac, AG7240_MII_MGMT_ADDRESS, addr);
ag7240_reg_wr(mac, AG7240_MII_MGMT_CTRL, data);
do {
rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;
}while (rddata && --ii);
if (ii==0)
printf("Error!!! Leave ag7240_miiphy_write without polling correct status!\n");
}
#endif /* CONFIG_MII */
@@ -0,0 +1,244 @@
#ifndef _AG7240_H
#define _AG7240_H
#include <linux/types.h>
/*
* h/w descriptor
*/
typedef struct {
uint32_t pkt_start_addr;
uint32_t is_empty : 1;
uint32_t res1 : 10;
uint32_t ftpp_override : 5;
uint32_t res2 : 4;
uint32_t pkt_size : 12;
uint32_t next_desc ;
}ag7240_desc_t;
#define NO_OF_TX_FIFOS 8
#define NO_OF_RX_FIFOS 8
typedef struct {
ag7240_desc_t *fifo_tx[NO_OF_TX_FIFOS];
ag7240_desc_t *fifo_rx[NO_OF_RX_FIFOS];
struct eth_device *dev;
u32 next_tx;
u32 next_rx;
u32 link;
u32 duplex;
u32 speed;
u32 mac_unit;
u32 mac_base;
}ag7240_mac_t;
#define ag7240_reg_wr(_mac, _x, _y) ar7240_reg_wr(((_x) + _mac->mac_base), (_y))
#define ag7240_reg_rd(_mac, _x) ar7240_reg_rd(((_x) + _mac->mac_base))
#define ag7240_reg_rmw_set(_mac, _x, _y) \
ar7240_reg_rmw_set(((_x) + _mac->mac_base ), (_y))
#define ag7240_reg_rmw_clear(_mac, _x, _y) \
ar7240_reg_rmw_clear(((_x) + _mac->mac_base), (_y))
#ifdef COMPRESSED_UBOOT
#define _1000BASET 1000
#define _100BASET 100
#define _10BASET 10
#endif /* #ifdef COMPRESSED_UBOOT */
/*
* spd is _1000BASET, _100BASET etc. defined in include/miiphy.h
*/
#define mii_reg(_mac) (AR7240_MII0_CTRL + ((_mac)->mac_unit * 4))
#define mii_if(_mac) (((_mac)->mac_unit == 0) ? mii0_if : mii1_if)
#define ag7240_set_mii_ctrl_speed(_mac, _spd) do { \
ar7240_reg_rmw_clear(mii_reg(_mac), (3 << 4)); \
ar7240_reg_rmw_set(mii_reg(_mac), ((_spd) << 4)); \
}while(0);
#if defined (CFG_MII0_GMII)
#define ag7240_get_mii_if() 0
#elif defined (CFG_MII0_MII)
#define ag7240_get_mii_if() 0
#elif defined (CFG_MII0_RGMII)
#define ag7240_get_mii_if() 0
#elif defined (CFG_MII0_RMII)
#define ag7240_get_mii_if() 0
#endif
#define MAX_WAIT 1000
/*
* Config/Mac Register definitions
*/
#define AG7240_MAC_CFG1 0x00
#define AG7240_MAC_CFG2 0x04
#define AG7240_MAC_IFCTL 0x38
#define AG7240_ETH_CFG4 0x58
#define AG7240_ETH_CFG5 0x5C
/*
* fifo control registers
*/
#define AG7240_MAC_FIFO_CFG_0 0x48
#define AG7240_MAC_FIFO_CFG_1 0x4c
#define AG7240_MAC_FIFO_CFG_2 0x50
#define AG7240_MAC_FIFO_CFG_3 0x54
#define AG7240_MAC_FIFO_CFG_4 0x58
#define AG7240_MAC_FIFO_CFG_5 0x5c
#define AG7240_BYTE_PER_CLK_EN (1 << 19)
#define AG7240_MAC_FIFO_RAM_0 0x60
#define AG7240_MAC_FIFO_RAM_1 0x64
#define AG7240_MAC_FIFO_RAM_2 0x68
#define AG7240_MAC_FIFO_RAM_3 0x6c
#define AG7240_MAC_FIFO_RAM_4 0x70
#define AG7240_MAC_FIFO_RAM_5 0x74
#define AG7240_MAC_FIFO_RAM_6 0x78
#define AG7240_MAC_FIFO_RAM_7 0x7c
/*
* fields
*/
#define AG7240_MAC_CFG1_SOFT_RST (1 << 31)
#define AG7240_MAC_CFG1_RX_RST (1 << 19)
#define AG7240_MAC_CFG1_TX_RST (1 << 18)
#define AG7240_MAC_CFG1_LOOPBACK (1 << 8)
#define AG7240_MAC_CFG1_RX_EN (1 << 2)
#define AG7240_MAC_CFG1_TX_EN (1 << 0)
#define AG7240_MAC_CFG2_FDX (1 << 0)
#define AG7240_MAC_CFG2_PAD_CRC_EN (1 << 2)
#define AG7240_MAC_CFG2_LEN_CHECK (1 << 4)
#define AG7240_MAC_CFG2_HUGE_FRAME_EN (1 << 5)
#define AG7240_MAC_CFG2_IF_1000 (1 << 9)
#define AG7240_MAC_CFG2_IF_10_100 (1 << 8)
#define AG7240_MAC_IFCTL_SPEED (1 << 16)
/*
* DMA (tx/rx) register defines
*/
#define AG7240_DMA_TX_CTRL 0x180
#define AG7240_DMA_TX_DESC 0x184
#define AG7240_DMA_TX_STATUS 0x188
#define AG7240_DMA_RX_CTRL 0x18c
#define AG7240_DMA_RX_DESC 0x190
#define AG7240_DMA_RX_STATUS 0x194
#define AG7240_DMA_INTR_MASK 0x198
#define AG7240_DMA_INTR 0x19c
/*
* tx/rx ctrl and status bits
*/
#define AG7240_TXE (1 << 0)
#define AG7240_TX_STATUS_PKTCNT_SHIFT 16
#define AG7240_TX_STATUS_PKT_SENT 0x1
#define AG7240_TX_STATUS_URN 0x2
#define AG7240_TX_STATUS_BUS_ERROR 0x8
#define AG7240_RXE (1 << 0)
#define AG7240_RX_STATUS_PKTCNT_MASK 0xff0000
#define AG7240_RX_STATUS_PKT_RCVD (1 << 0)
#define AG7240_RX_STATUS_OVF (1 << 2)
#define AG7240_RX_STATUS_BUS_ERROR (1 << 3)
/*
* Int and int mask
*/
#define AG7240_INTR_TX (1 << 0)
#define AG7240_INTR_TX_URN (1 << 1)
#define AG7240_INTR_TX_BUS_ERROR (1 << 3)
#define AG7240_INTR_RX (1 << 4)
#define AG7240_INTR_RX_OVF (1 << 6)
#define AG7240_INTR_RX_BUS_ERROR (1 << 7)
/*
* MII registers
*/
#define AG7240_MAC_MII_MGMT_CFG 0x20
#define AG7240_MGMT_CFG_CLK_DIV_20 0x07
#define AG7240_MII_MGMT_CMD 0x24
#define AG7240_MGMT_CMD_READ 0x1
#define AG7240_MII_MGMT_ADDRESS 0x28
#define AG7240_ADDR_SHIFT 8
#define AG7240_MII_MGMT_CTRL 0x2c
#define AG7240_MII_MGMT_STATUS 0x30
#define AG7240_MII_MGMT_IND 0x34
#define AG7240_MGMT_IND_BUSY (1 << 0)
#define AG7240_MGMT_IND_INVALID (1 << 2)
#define AG7240_GE_MAC_ADDR1 0x40
#define AG7240_GE_MAC_ADDR2 0x44
/*
* Ethernet config registers
*/
#define AG7240_ETH_CFG 0x18070000
#define AG7240_ETH_CFG_RGMII_GE0 (1<<0)
#define AG7240_ETH_CFG_MII_GE0 (1<<1)
#define AG7240_ETH_CFG_GMII_GE0 (1<<2)
#define AG7240_ETH_CFG_RMII_GE0 (1<<10)
#define AG7240_ETH_CFG_RMII_HISPD_GE0 (1<<11)
#define AG7240_ETH_CFG_RMII_MASTER_MODE (1<<12)
#define AG7240_ETH_CFG_MII_GE0_MASTER (1<<3)
#define AG7240_ETH_CFG_MII_GE0_SLAVE (1<<4)
#define AG7240_ETH_CFG_GE0_ERR_EN (1<<5)
#define AG7240_ETH_CFG_SW_ONLY_MODE (1<<6)
#define AG7240_ETH_CFG_SW_PHY_SWAP (1<<7)
#define AG7240_ETH_CFG_SW_PHY_ADDR_SWAP (1<<8)
#define AG7240_ETH_CFG_RXD_DELAY (1 << 14)
#define AG7240_ETH_CFG_RDV_DELAY (1 << 16)
#define AG7240_ETH_SWITCH_CLK_SPARE 0x18050024
/*
* * ownership of descriptors between DMA and cpu
* */
#define ag7240_rx_owned_by_dma(_ds) ((_ds)->is_empty == 1)
#define ag7240_rx_give_to_dma(_ds) ((_ds)->is_empty = 1)
#define ag7240_tx_owned_by_dma(_ds) ((_ds)->is_empty == 0)
#define ag7240_tx_give_to_dma(_ds) ((_ds)->is_empty = 0)
#define ag7240_tx_own(_ds) ((_ds)->is_empty = 1)
/*
* link settings
*/
#define ag7240_set_mac_duplex(_mac, _fdx) do { \
if ((_fdx)) \
ag7240_reg_rmw_set(_mac, AG7240_MAC_CFG2, AG7240_MAC_CFG2_FDX) \
else \
ag7240_reg_rmw_clear(_mac, AG7240_MAC_CFG2, AG7240_MAC_CFG2_FDX) \
}while(0)
#define ag7240_set_mac_if(_mac, _isXGMII) do { \
ag7240_reg_rmw_clear(_mac, AG7240_MAC_CFG2, AG7240_MAC_CFG2_IF_1000| \
AG7240_MAC_CFG2_IF_10_100); \
if ((_isXGMII)) { \
ag7240_reg_rmw_set(_mac, AG7240_MAC_CFG2, AG7240_MAC_CFG2_IF_1000) \
ag7240_reg_rmw_set(_mac, AG7240_MAC_FIFO_CFG_5, AG7240_BYTE_PER_CLK_EN);\
} \
else { \
ag7240_reg_rmw_set(_mac, AG7240_MAC_CFG2, AG7240_MAC_CFG2_IF_10_100)\
ag7240_reg_rmw_clear(_mac, AG7240_MAC_FIFO_CFG_5, AG7240_BYTE_PER_CLK_EN);\
} \
}while(0)
#define ag7240_set_mac_speed(_mac, _is100) do { \
if ((_is100)) \
ag7240_reg_rmw_set(_mac, AG7240_MAC_IFCTL, AG7240_MAC_IFCTL_SPEED) \
else \
ag7240_reg_rmw_clear(_mac, AG7240_MAC_IFCTL, AG7240_MAC_IFCTL_SPEED)\
}while(0)
#endif
@@ -0,0 +1,117 @@
#ifndef _AG7240_PHY_H
#define _AG7240_PHY_H
static inline void ag7240_phy_setup(int unit)
{
#ifdef CONFIG_AR7242_S16_PHY
if ((is_ar7242() || is_wasp()) && (unit==0)) {
athrs16_phy_setup(unit);
} else
#endif
#ifdef CONFIG_ATHRS17_PHY
if (unit == 0) {
athrs17_phy_setup(unit);
} else
#endif
{
#ifdef CFG_ATHRS27_PHY
athrs27_phy_setup(unit);
#endif
#ifdef CFG_ATHRS26_PHY
athrs26_phy_setup(unit);
#endif
#if defined(CONFIG_F1E_PHY) || defined(CONFIG_F2E_PHY)
athr_phy_setup(unit);
#endif
#ifdef CONFIG_VIR_PHY
athr_vir_phy_setup(unit);
#endif
}
}
static inline void ag7240_phy_link(int unit, u32 *link)
{
#ifdef CONFIG_AR7242_S16_PHY
if ((is_ar7242() || is_wasp()) && (unit==0)) {
*link = athrs16_phy_is_up(unit);
} else
#endif
#ifdef CONFIG_ATHRS17_PHY
if (unit == 0) {
*link = athrs17_phy_is_up(unit);
} else
#endif
{
#ifdef CFG_ATHRS27_PHY
*link = athrs27_phy_is_up(unit);
#endif
#ifdef CFG_ATHRS26_PHY
*link = athrs26_phy_is_up(unit);
#endif
#if defined(CONFIG_F1E_PHY) || defined(CONFIG_F2E_PHY)
*link = athr_phy_is_up(unit);
#endif
#ifdef CONFIG_VIR_PHY
*link = athr_vir_phy_is_up(unit);
#endif
}
}
static inline void ag7240_phy_duplex(int unit, u32 *duplex)
{
#ifdef CONFIG_AR7242_S16_PHY
if ((is_ar7242() || is_wasp()) && (unit==0)) {
*duplex = athrs16_phy_is_fdx(unit);
} else
#endif
#ifdef CONFIG_ATHRS17_PHY
if (unit == 0) {
*duplex = athrs17_phy_is_fdx(unit);
} else
#endif
{
#ifdef CFG_ATHRS27_PHY
*duplex = athrs27_phy_is_fdx(unit, 0/* FIXME */);
#endif
#ifdef CFG_ATHRS26_PHY
*duplex = athrs26_phy_is_fdx(unit);
#endif
#if defined(CONFIG_F1E_PHY) || defined(CONFIG_F2E_PHY)
*duplex = athr_phy_is_fdx(unit);
#endif
#ifdef CONFIG_VIR_PHY
*duplex = athr_vir_phy_is_fdx(unit);
#endif
}
}
static inline void ag7240_phy_speed(int unit, u32 *speed)
{
#ifdef CONFIG_AR7242_S16_PHY
if ((is_ar7242() || is_wasp()) && (unit==0)) {
*speed = athrs16_phy_speed(unit);
} else
#endif
#ifdef CONFIG_ATHRS17_PHY
if (unit == 0) {
*speed = athrs17_phy_speed(unit);
} else
#endif
{
#ifdef CFG_ATHRS27_PHY
*speed = athrs27_phy_speed(unit, 0/* FIXME */);
#endif
#ifdef CFG_ATHRS26_PHY
*speed = athrs26_phy_speed(unit);
#endif
#if defined(CONFIG_F1E_PHY) || defined(CONFIG_F2E_PHY)
*speed = athr_phy_speed(unit);
#endif
#ifdef CONFIG_VIR_PHY
*speed = athr_vir_phy_speed(unit);
#endif
}
}
#endif /*_AG7240_PHY_H*/
@@ -0,0 +1,142 @@
#include <common.h>
#include <asm/addrspace.h>
#include <asm/types.h>
#include <ar7240_soc.h>
#define REG_OFFSET 4
/* === END OF CONFIG === */
/* register offset */
#define OFS_RCV_BUFFER (0*REG_OFFSET)
#define OFS_TRANS_HOLD (0*REG_OFFSET)
#define OFS_SEND_BUFFER (0*REG_OFFSET)
#define OFS_INTR_ENABLE (1*REG_OFFSET)
#define OFS_INTR_ID (2*REG_OFFSET)
#define OFS_DATA_FORMAT (3*REG_OFFSET)
#define OFS_LINE_CONTROL (3*REG_OFFSET)
#define OFS_MODEM_CONTROL (4*REG_OFFSET)
#define OFS_RS232_OUTPUT (4*REG_OFFSET)
#define OFS_LINE_STATUS (5*REG_OFFSET)
#define OFS_MODEM_STATUS (6*REG_OFFSET)
#define OFS_RS232_INPUT (6*REG_OFFSET)
#define OFS_SCRATCH_PAD (7*REG_OFFSET)
#define OFS_DIVISOR_LSB (0*REG_OFFSET)
#define OFS_DIVISOR_MSB (1*REG_OFFSET)
#define MY_WRITE(y, z) ((*((volatile u32*)(y))) = z)
#define UART16550_READ(y) ar7240_reg_rd((AR7240_UART_BASE+y))
#define UART16550_WRITE(x, z) ar7240_reg_wr((AR7240_UART_BASE+x), z)
void
ar7240_sys_frequency(u32 *cpu_freq, u32 *ddr_freq, u32 *ahb_freq)
{
u32 pll, pll_div, ref_div, ahb_div, ddr_div, freq;
pll = ar7240_reg_rd(AR7240_CPU_PLL_CONFIG);
pll_div =
((pll & PLL_CONFIG_PLL_DIV_MASK) >> PLL_CONFIG_PLL_DIV_SHIFT);
ref_div =
((pll & PLL_CONFIG_PLL_REF_DIV_MASK) >> PLL_CONFIG_PLL_REF_DIV_SHIFT);
ddr_div =
((pll & PLL_CONFIG_DDR_DIV_MASK) >> PLL_CONFIG_DDR_DIV_SHIFT) + 1;
ahb_div =
(((pll & PLL_CONFIG_AHB_DIV_MASK) >> PLL_CONFIG_AHB_DIV_SHIFT) + 1)*2;
freq = pll_div * ref_div * 5000000;
if (cpu_freq)
*cpu_freq = freq;
if (ddr_freq)
*ddr_freq = freq/ddr_div;
if (ahb_freq)
*ahb_freq = freq/ahb_div;
}
int serial_init(void)
{
u32 div,val;
u32 ahb_freq __maybe_unused, ddr_freq __maybe_unused, cpu_freq __maybe_unused;
#ifdef CONFIG_WASP
val = ar7240_reg_rd(WASP_BOOTSTRAP_REG);
if ((val & WASP_REF_CLK_25) == 0) {
div = (25 * 1000000) / (16 * CONFIG_BAUDRATE);
} else {
div = (40 * 1000000) / (16 * CONFIG_BAUDRATE);
}
#else
ar7240_sys_frequency(&cpu_freq, &ddr_freq, &ahb_freq);
div = ahb_freq/(16 * CONFIG_BAUDRATE);
MY_WRITE(0xb8040000, 0xcff);
MY_WRITE(0xb8040008, 0x3b);
val = ar7240_reg_rd(0xb8040028);
MY_WRITE(0xb8040028,(val | 0x8002));
MY_WRITE(0xb8040008, 0x2f);
#endif
/*
* set DIAB bit
*/
UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
/* set divisor */
UART16550_WRITE(OFS_DIVISOR_LSB, (div & 0xff));
UART16550_WRITE(OFS_DIVISOR_MSB, ((div >> 8) & 0xff));
/* clear DIAB bit*/
UART16550_WRITE(OFS_LINE_CONTROL, 0x00);
/* set data format */
UART16550_WRITE(OFS_DATA_FORMAT, 0x3);
UART16550_WRITE(OFS_INTR_ENABLE, 0);
return 0;
}
int serial_tstc (void)
{
return(UART16550_READ(OFS_LINE_STATUS) & 0x1);
}
int serial_getc(void)
{
while(!serial_tstc());
return UART16550_READ(OFS_RCV_BUFFER);
}
void serial_putc(const char byte)
{
if (byte == '\n') serial_putc ('\r');
while (((UART16550_READ(OFS_LINE_STATUS)) & 0x20) == 0x0);
UART16550_WRITE(OFS_SEND_BUFFER, byte);
}
void serial_setbrg (void)
{
}
void serial_puts (const char *s)
{
while (*s)
{
serial_putc (*s++);
}
}
@@ -0,0 +1,34 @@
#ifndef _HORNET_H
#define _HORNET_H
/*
* GE0 AR8021 phy address
*/
#define GE0_AR8021_PHY_ADDR 0x0
/*
* Ethernet config registers
*/
#define AG7240_ETH_CFG 0x18070000
#define AG7240_ETH_CFG_RGMII_GE0 (1<<0)
#define AG7240_ETH_CFG_MII_GE0 (1<<1)
#define AG7240_ETH_CFG_GMII_GE0 (1<<2)
#define AG7240_ETH_CFG_MII_GE0_MASTER (1<<3)
#define AG7240_ETH_CFG_MII_GE0_SLAVE (1<<4)
#define AG7240_ETH_CFG_GE0_ERR_EN (1<<5)
#define AG7240_ETH_CFG_SW_ONLY_MODE (1<<6)
#define AG7240_ETH_CFG_SW_PHY_SWAP (1<<7)
#define AG7240_ETH_CFG_SW_PHY_ADDR_SWAP (1<<8)
/* Phy Specific status fields */
#define ATHER_STATUS_LINK_MASK 0xC000
#define ATHER_STATUS_LINK_SHIFT 14
#define ATHER_STATUS_FULL_DEPLEX 0x2000
#define ATHR_STATUS_LINK_PASS 0x0400
#define ATHR_LATCH_LINK_PASS 0x0004
#ifndef ag7240_unit2name
#define ag7240_unit2name(_unit) _unit ? "eth1" : "eth0"
#endif
#endif
@@ -0,0 +1,662 @@
#include <config.h>
#include <common.h>
#include <malloc.h>
#include <net.h>
#include <command.h>
#include <asm/io.h>
#include <asm/addrspace.h>
#include <asm/types.h>
#include "ar7240_soc.h"
#include "ag7240.h"
#include "ag7240_phy.h"
#ifdef CONFIG_MII
#include <miiphy.h>
#endif
#define ag7240_unit2mac(_unit) ag7240_macs[(_unit)]
#define ag7240_name2mac(name) strcmp(name,"eth0") ? ag7240_unit2mac(1) : ag7240_unit2mac(0)
uint16_t ag7240_miiphy_read(char *devname, uint32_t phaddr,
uint8_t reg);
void ag7240_miiphy_write(char *devname, uint32_t phaddr,
uint8_t reg, uint16_t data);
ag7240_mac_t *ag7240_macs[CFG_AG7240_NMACS];
extern int athrs26_phy_setup(int unit);
extern int athrs26_phy_is_up(int unit);
extern int athrs26_phy_is_fdx(int unit);
extern int athrs26_phy_speed(int unit);
extern void athrs26_reg_init(void);
extern void athrs26_reg_init_lan(void);
extern void ar7240_sys_frequency(u32 *cpu_freq, u32 *ddr_freq, u32 *ahb_freq);
extern int athrs26_mdc_check(void);
#ifdef CONFIG_HORNET_EMU
#include "hornet.h"
void ar8021_phy_setup(u32 ethUnit, u32 phyUnit);
uint32_t ar8021_phy_is_link_alive(u32 ethUnit, u32 phyUnit);
uint32_t ar8021_phy_is_fdx(u32 ethUnit, u32 phyUnit);
uint32_t ar8021_phy_speed(u32 ethUnit, u32 phyUnit);
#endif /* CONFIG_HORNET_EMU */
static int
ag7240_send(struct eth_device *dev, volatile void *packet, int length)
{
int i;
ag7240_mac_t *mac = (ag7240_mac_t *)dev->priv;
ag7240_desc_t *f = mac->fifo_tx[mac->next_tx];
f->pkt_size = length;
f->res1 = 0;
f->pkt_start_addr = virt_to_phys(packet);
ag7240_tx_give_to_dma(f);
flush_cache((u32) packet, length);
ag7240_reg_wr(mac, AG7240_DMA_TX_DESC, virt_to_phys(f));
ag7240_reg_wr(mac, AG7240_DMA_TX_CTRL, AG7240_TXE);
for (i = 0; i < MAX_WAIT; i++) {
udelay(10);
if (!ag7240_tx_owned_by_dma(f))
break;
}
if (i == MAX_WAIT)
printf("Tx Timed out\n");
f->pkt_start_addr = 0;
f->pkt_size = 0;
if (++mac->next_tx >= NO_OF_TX_FIFOS)
mac->next_tx = 0;
return (0);
}
static int ag7240_recv(struct eth_device *dev)
{
int length;
ag7240_desc_t *f;
ag7240_mac_t *mac;
mac = (ag7240_mac_t *)dev->priv;
for (;;) {
f = mac->fifo_rx[mac->next_rx];
if (ag7240_rx_owned_by_dma(f))
break;
length = f->pkt_size;
NetReceive(NetRxPackets[mac->next_rx] , length - 4);
flush_cache((u32) NetRxPackets[mac->next_rx] , PKTSIZE_ALIGN);
ag7240_rx_give_to_dma(f);
if (++mac->next_rx >= NO_OF_RX_FIFOS)
mac->next_rx = 0;
}
if (!(ag7240_reg_rd(mac, AG7240_DMA_RX_CTRL))) {
ag7240_reg_wr(mac, AG7240_DMA_RX_DESC, virt_to_phys(f));
ag7240_reg_wr(mac, AG7240_DMA_RX_CTRL, 1);
}
return (0);
}
static void ag7240_hw_start(ag7240_mac_t *mac)
{
u32 cpu_freq,ddr_freq,ahb_freq;
u32 mgmt_cfg_val;
u32 check_cnt,revid_val;
if(mac->mac_unit)
{
ag7240_reg_wr(mac, AG7240_MAC_CFG1, (AG7240_MAC_CFG1_RX_EN |
AG7240_MAC_CFG1_TX_EN));
ag7240_reg_rmw_set(mac, AG7240_MAC_CFG2, (AG7240_MAC_CFG2_PAD_CRC_EN |
AG7240_MAC_CFG2_LEN_CHECK | AG7240_MAC_CFG2_IF_1000));
}
else {
ag7240_reg_wr(mac, AG7240_MAC_CFG1, (AG7240_MAC_CFG1_RX_EN |
AG7240_MAC_CFG1_TX_EN));
ag7240_reg_rmw_set(mac, AG7240_MAC_CFG2, (AG7240_MAC_CFG2_PAD_CRC_EN |
AG7240_MAC_CFG2_LEN_CHECK));
}
#ifdef AR7240_EMU
printf("AG7240_MAC_FIFO_CFG_4\n");
ag7240_reg_rmw_set(mac, AG7240_MAC_FIFO_CFG_4, 0x3ffff);
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_1, 0x10ffff);
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_2, 0xAAA0555);
#else
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_1, 0xfff0000);
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_2, 0x1fff);
#endif
if ((ar7240_reg_rd(AR7240_REV_ID) & AR7240_REV_ID_MASK) == AR7240_REV_1_2) {
mgmt_cfg_val = 0x2;
if (mac->mac_unit == 0) {
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
}
}
else {
ar7240_sys_frequency(&cpu_freq, &ddr_freq, &ahb_freq);
switch (ahb_freq/1000000) {
case 150:
mgmt_cfg_val = 0x7;
break;
case 175:
mgmt_cfg_val = 0x5;
break;
case 200:
mgmt_cfg_val = 0x4;
break;
case 210:
mgmt_cfg_val = 0x9;
break;
case 220:
mgmt_cfg_val = 0x9;
break;
default:
mgmt_cfg_val = 0x7;
}
if ((is_ar7241() || is_ar7242())) {
/* External MII mode */
if (mac->mac_unit == 0 && is_ar7242()) {
mgmt_cfg_val = 0x6;
ar7240_reg_rmw_set(AG7240_ETH_CFG, AG7240_ETH_CFG_RGMII_GE0);
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
}
#ifndef CONFIG_HORNET_EMU
/* Virian */
mgmt_cfg_val = 0x4;
ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(ag7240_macs[1], AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
printf("Virian MDC CFG Value ==> %x\n",mgmt_cfg_val);
#endif
}
else { /* Python 1.0 & 1.1 */
if (mac->mac_unit == 0) {
check_cnt = 0;
while (check_cnt++ < 10) {
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val | (1 << 31));
ag7240_reg_wr(mac, AG7240_MAC_MII_MGMT_CFG, mgmt_cfg_val);
if(athrs26_mdc_check() == 0)
break;
}
if(check_cnt == 11)
printf("%s: MDC check failed\n", __func__);
}
}
}
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_0, 0x1f00);
ag7240_reg_rmw_set(mac, AG7240_MAC_FIFO_CFG_4, 0x3ffff);
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_1, 0x10ffff);
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_2, 0xAAA0555);
/*
* Setting Drop CRC Errors, Pause Frames,Length Error frames
* and Multi/Broad cast frames.
*/
#ifdef CONFIG_HORNET_EMU
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_5, 0xbefff);
#else
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_5, 0x7eccf);
#endif
ag7240_reg_wr(mac, AG7240_MAC_FIFO_CFG_3, 0x1f00140);
printf(": cfg1 %#x cfg2 %#x\n", ag7240_reg_rd(mac, AG7240_MAC_CFG1),
ag7240_reg_rd(mac, AG7240_MAC_CFG2));
}
static int ag7240_check_link(ag7240_mac_t *mac)
{
u32 link, duplex, speed, fdx;
#ifdef CONFIG_HORNET_EMU
link = ar8021_phy_is_link_alive(0, GE0_AR8021_PHY_ADDR);
duplex = ar8021_phy_is_fdx(0, GE0_AR8021_PHY_ADDR);
speed = ar8021_phy_speed(0, GE0_AR8021_PHY_ADDR);
#else
ag7240_phy_link(mac->mac_unit, &link);
ag7240_phy_duplex(mac->mac_unit, &duplex);
ag7240_phy_speed(mac->mac_unit, &speed);
#endif
mac->link = link;
#ifdef SUPPORT_PLC
if(strcmp(mac->dev->name, "eth0") == 0) {
printf("ag7240_check_link: %s link forced down\n",mac->dev->name);
return 0;
}
#endif
if(!mac->link) {
printf("%s link down\n",mac->dev->name);
return 0;
}
switch (speed)
{
case _1000BASET:
ag7240_set_mac_if(mac, 1);
ag7240_reg_rmw_set(mac, AG7240_MAC_FIFO_CFG_5, (1 << 19));
if (is_ar7242() && (mac->mac_unit == 0))
ar7240_reg_wr(AR7242_ETH_XMII_CONFIG,0x1c000000);
break;
case _100BASET:
ag7240_set_mac_if(mac, 0);
ag7240_set_mac_speed(mac, 1);
ag7240_reg_rmw_clear(mac, AG7240_MAC_FIFO_CFG_5, (1 << 19));
#ifndef CONFIG_HORNET_EMU
if (is_ar7242() && (mac->mac_unit == 0))
ar7240_reg_wr(AR7242_ETH_XMII_CONFIG,0x0101);
#endif
break;
case _10BASET:
ag7240_set_mac_if(mac, 0);
ag7240_set_mac_speed(mac, 0);
ag7240_reg_rmw_clear(mac, AG7240_MAC_FIFO_CFG_5, (1 << 19));
if (is_ar7242() && (mac->mac_unit == 0))
ar7240_reg_wr(AR7242_ETH_XMII_CONFIG,0x1616);
break;
default:
printf("Invalid speed detected\n");
return 0;
}
if (mac->link && (duplex == mac->duplex) && (speed == mac->speed))
return 1;
mac->duplex = duplex;
mac->speed = speed;
printf("dup %d speed %d\n", duplex, speed);
ag7240_set_mac_duplex(mac,duplex);
return 1;
}
/*
* For every command we re-setup the ring and start with clean h/w rx state
*/
static int ag7240_clean_rx(struct eth_device *dev, bd_t * bd)
{
int i;
ag7240_desc_t *fr;
ag7240_mac_t *mac = (ag7240_mac_t*)dev->priv;
if (!ag7240_check_link(mac))
return 0;
mac->next_rx = 0;
for (i = 0; i < NO_OF_RX_FIFOS; i++) {
fr = mac->fifo_rx[i];
fr->pkt_start_addr = virt_to_phys(NetRxPackets[i]);
flush_cache((u32) NetRxPackets[i], PKTSIZE_ALIGN);
ag7240_rx_give_to_dma(fr);
}
ag7240_reg_wr(mac, AG7240_DMA_RX_DESC, virt_to_phys(mac->fifo_rx[0]));
ag7240_reg_wr(mac, AG7240_DMA_RX_CTRL, AG7240_RXE); /* rx start */
udelay(1000 * 1000);
return 1;
}
static int ag7240_alloc_fifo(int ndesc, ag7240_desc_t ** fifo)
{
int i;
u32 size;
uchar *p = NULL;
size = sizeof(ag7240_desc_t) * ndesc;
size += CONFIG_SYS_CACHELINE_SIZE - 1;
if ((p = malloc(size)) == NULL) {
printf("Cant allocate fifos\n");
return -1;
}
p = (uchar *) (((u32) p + CONFIG_SYS_CACHELINE_SIZE - 1) &
~(CONFIG_SYS_CACHELINE_SIZE - 1));
p = UNCACHED_SDRAM(p);
for (i = 0; i < ndesc; i++)
fifo[i] = (ag7240_desc_t *) p + i;
return 0;
}
static int ag7240_setup_fifos(ag7240_mac_t *mac)
{
int i;
if (ag7240_alloc_fifo(NO_OF_TX_FIFOS, mac->fifo_tx))
return 1;
for (i = 0; i < NO_OF_TX_FIFOS; i++) {
mac->fifo_tx[i]->next_desc = (i == NO_OF_TX_FIFOS - 1) ?
virt_to_phys(mac->fifo_tx[0]) : virt_to_phys(mac->fifo_tx[i + 1]);
ag7240_tx_own(mac->fifo_tx[i]);
}
if (ag7240_alloc_fifo(NO_OF_RX_FIFOS, mac->fifo_rx))
return 1;
for (i = 0; i < NO_OF_RX_FIFOS; i++) {
mac->fifo_rx[i]->next_desc = (i == NO_OF_RX_FIFOS - 1) ?
virt_to_phys(mac->fifo_rx[0]) : virt_to_phys(mac->fifo_rx[i + 1]);
}
return (1);
}
static void ag7240_halt(struct eth_device *dev)
{
ag7240_mac_t *mac = (ag7240_mac_t *)dev->priv;
ag7240_reg_wr(mac, AG7240_DMA_RX_CTRL, 0);
while (ag7240_reg_rd(mac, AG7240_DMA_RX_CTRL));
}
unsigned char *
ag7240_mac_addr_loc(void)
{
extern flash_info_t flash_info[];
#ifdef BOARDCAL
/*
** BOARDCAL environmental variable has the address of the cal sector
*/
return ((unsigned char *)BOARDCAL);
#else
/* MAC address is store in the 2nd 4k of last sector */
return ((unsigned char *)
(KSEG1ADDR(AR7240_SPI_BASE) + (4 * 1024) +
flash_info[0].size - (64 * 1024) /* sector_size */ ));
#endif
}
static void ag7240_get_ethaddr(struct eth_device *dev)
{
unsigned char *eeprom;
unsigned char *mac = dev->enetaddr;
eeprom = ag7240_mac_addr_loc();
if (strcmp(dev->name, "eth0") == 0) {
memcpy(mac, eeprom, 6);
} else if (strcmp(dev->name, "eth1") == 0) {
eeprom += 6;
memcpy(mac, eeprom, 6);
} else {
printf("%s: unknown ethernet device %s\n", __func__, dev->name);
return;
}
/* Use fixed address if the above address is invalid */
if (mac[0] != 0x00 || (mac[0] == 0xff && mac[5] == 0xff)) {
mac[0] = 0x00;
mac[1] = 0x03;
mac[2] = 0x7f;
mac[3] = 0x09;
mac[4] = 0x0b;
mac[5] = 0xad;
printf("No valid address in Flash. Using fixed address\n");
} else {
printf("Fetching MAC Address from 0x%p\n", __func__, eeprom);
}
}
int ag7240_enet_initialize(bd_t * bis)
{
struct eth_device *dev[CFG_AG7240_NMACS];
u32 mask, mac_h, mac_l;
int i;
printf("ag7240_enet_initialize...\n");
#ifdef CONFIG_MACH_HORNET
ar7240_reg_wr(HORNET_BOOTSTRAP_STATUS, ar7240_reg_rd(HORNET_BOOTSTRAP_STATUS) & ~HORNET_BOOTSTRAP_MDIO_SLAVE_MASK);
#endif
for (i = 0;i < CFG_AG7240_NMACS;i++) {
if ((dev[i] = (struct eth_device *) malloc(sizeof (struct eth_device))) == NULL) {
puts("malloc failed\n");
return 0;
}
if ((ag7240_macs[i] = (ag7240_mac_t *) malloc(sizeof (ag7240_mac_t))) == NULL) {
puts("malloc failed\n");
return 0;
}
memset(ag7240_macs[i], 0, sizeof(ag7240_macs[i]));
memset(dev[i], 0, sizeof(dev[i]));
sprintf(dev[i]->name, "eth%d", i);
ag7240_get_ethaddr(dev[i]);
ag7240_macs[i]->mac_unit = i;
ag7240_macs[i]->mac_base = i ? AR7240_GE1_BASE : AR7240_GE0_BASE ;
ag7240_macs[i]->dev = dev[i];
dev[i]->iobase = 0;
dev[i]->init = ag7240_clean_rx;
dev[i]->halt = ag7240_halt;
dev[i]->send = ag7240_send;
dev[i]->recv = ag7240_recv;
dev[i]->priv = (void *)ag7240_macs[i];
}
for (i = 0;i < CFG_AG7240_NMACS;i++) {
eth_register(dev[i]);
#ifdef CONFIG_MII
miiphy_register(dev[i]->name, ag7240_miiphy_read, ag7240_miiphy_write);
#endif
if(!i) {
mask = (AR7240_RESET_GE0_MAC | AR7240_RESET_GE0_PHY |
AR7240_RESET_GE1_MAC | AR7240_RESET_GE1_PHY);
if ((is_ar7241() || is_ar7242()))
mask = mask | AR7240_RESET_GE0_MDIO | AR7240_RESET_GE1_MDIO;
ar7240_reg_rmw_set(AR7240_RESET, mask);
udelay(1000 * 100);
ar7240_reg_rmw_clear(AR7240_RESET, mask);
udelay(1000 * 100);
udelay(10 * 1000);
}
ag7240_hw_start(ag7240_macs[i]);
ag7240_setup_fifos(ag7240_macs[i]);
udelay(100 * 1000);
{
unsigned char *mac = dev[i]->enetaddr;
printf("%s: %02x:%02x:%02x:%02x:%02x:%02x\n", dev[i]->name,
mac[0] & 0xff, mac[1] & 0xff, mac[2] & 0xff,
mac[3] & 0xff, mac[4] & 0xff, mac[5] & 0xff);
}
mac_l = (dev[i]->enetaddr[4] << 8) | (dev[i]->enetaddr[5]);
mac_h = (dev[i]->enetaddr[0] << 24) | (dev[i]->enetaddr[1] << 16) |
(dev[i]->enetaddr[2] << 8) | (dev[i]->enetaddr[3] << 0);
ag7240_reg_wr(ag7240_macs[i], AG7240_GE_MAC_ADDR1, mac_l);
ag7240_reg_wr(ag7240_macs[i], AG7240_GE_MAC_ADDR2, mac_h);
/* if using header for register configuration, we have to */
/* configure s26 register after frame transmission is enabled */
#ifdef CONFIG_HORNET_EMU
ar8021_phy_setup(0, GE0_AR8021_PHY_ADDR);
#else
if (ag7240_macs[i]->mac_unit == 0) { /* WAN Phy */
#ifdef CONFIG_AR7242_S16_PHY
if (is_ar7242()) {
athrs16_reg_init();
} else
#endif
{
athrs26_reg_init();
}
} else {
athrs26_reg_init_lan();
}
ag7240_phy_setup(ag7240_macs[i]->mac_unit);
#endif
printf("%s up\n",dev[i]->name);
}
return 1;
}
#ifdef CONFIG_MII
uint16_t
ag7240_miiphy_read(char *devname, uint32_t phy_addr, uint8_t reg)
{
ag7240_mac_t *mac = ag7240_name2mac(devname);
uint16_t addr = (phy_addr << AG7240_ADDR_SHIFT) | reg, val;
volatile int rddata;
uint16_t ii = 0x1000;
ag7240_reg_wr(mac, AG7240_MII_MGMT_CMD, 0x0);
ag7240_reg_wr(mac, AG7240_MII_MGMT_ADDRESS, addr);
ag7240_reg_wr(mac, AG7240_MII_MGMT_CMD, AG7240_MGMT_CMD_READ);
do
{
udelay(5);
rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;
}while(rddata && --ii);
val = ag7240_reg_rd(mac, AG7240_MII_MGMT_STATUS);
ag7240_reg_wr(mac, AG7240_MII_MGMT_CMD, 0x0);
return val;
}
void
ag7240_miiphy_write(char *devname, uint32_t phy_addr, uint8_t reg, uint16_t data)
{
ag7240_mac_t *mac = ag7240_name2mac(devname);
uint16_t addr = (phy_addr << AG7240_ADDR_SHIFT) | reg;
volatile int rddata;
uint16_t ii = 0x1000;
ag7240_reg_wr(mac, AG7240_MII_MGMT_ADDRESS, addr);
ag7240_reg_wr(mac, AG7240_MII_MGMT_CTRL, data);
do
{
rddata = ag7240_reg_rd(mac, AG7240_MII_MGMT_IND) & 0x1;
}while(rddata && --ii);
}
#endif /* CONFIG_MII */
#ifdef CONFIG_HORNET_EMU
void
ar8021_phy_setup(u32 ethUnit, u32 phyUnit)
{
uint32_t phyid1, phyid2;
phyid1 = ag7240_miiphy_read(ag7240_unit2name(ethUnit), phyUnit, 0x2);
phyid2 = ag7240_miiphy_read(ag7240_unit2name(ethUnit), phyUnit, 0x3);
printf("%s Phy ID %x:%x\n", __FUNCTION__, phyid1, phyid2);
udelay(1000*1000);
ar7240_reg_rmw_set(AR7240_GPIO_BASE, 0x20);
ar7240_reg_rmw_set(AR7240_GPIO_BASE + 0x8, 0x20);
udelay(1000*1000);
ar7240_reg_rmw_clear(AR7240_GPIO_BASE + 0x8, 0x20);
udelay(1000*1000);
}
uint32_t
ar8021_phy_is_link_alive(u32 ethUnit, u32 phyUnit)
{
uint32_t phyHwStatus;
phyHwStatus = ag7240_miiphy_read(ag7240_unit2name(ethUnit), phyUnit, 0x11);
if (phyHwStatus & ATHR_STATUS_LINK_PASS)
return 1;
return 0;
}
uint32_t
ar8021_phy_speed(uint32_t ethUnit, uint32_t phyUnit)
{
uint32_t phyHwStatus;
phyHwStatus = ag7240_miiphy_read(ag7240_unit2name(ethUnit), phyUnit, 0x11);
{
phyHwStatus = ((phyHwStatus & ATHER_STATUS_LINK_MASK) >>
ATHER_STATUS_LINK_SHIFT);
switch(phyHwStatus) {
case 0:
return _10BASET;
case 1:
return _100BASET;
case 2:
return _1000BASET;
default:
printf("Unkown speed read!\n");
}
}
return _10BASET;
}
uint32_t
ar8021_phy_is_fdx(u32 ethUnit, u32 phyUnit)
{
uint32_t phyHwStatus;
phyHwStatus = ag7240_miiphy_read(ag7240_unit2name(ethUnit), phyUnit, 0x11);
if (phyHwStatus & ATHER_STATUS_FULL_DEPLEX)
return 1;
return 0;
}
#endif /* CONFIG_HORNET_EMU */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,216 @@
#include <asm/addrspace.h>
#include <asm/types.h>
#include <config.h>
#include <hornet_soc.h>
#define uart_reg_read(x) ar7240_reg_rd( (AR7240_UART_BASE+x) )
#define uart_reg_write(x, y) ar7240_reg_wr( (AR7240_UART_BASE+x), y)
static int
AthrUartGet(char *__ch_data)
{
u32 rdata;
rdata = uart_reg_read(UARTDATA_ADDRESS);
if (UARTDATA_UARTRXCSR_GET(rdata)) {
*__ch_data = (char)UARTDATA_UARTTXRXDATA_GET(rdata);
rdata = UARTDATA_UARTRXCSR_SET(1);
uart_reg_write(UARTDATA_ADDRESS, rdata);
return 1;
}
else {
return 0;
}
}
static void
AthrUartPut(char __ch_data)
{
u32 rdata;
do {
rdata = uart_reg_read(UARTDATA_ADDRESS);
} while (UARTDATA_UARTTXCSR_GET(rdata) == 0);
rdata = UARTDATA_UARTTXRXDATA_SET((u32)__ch_data);
rdata |= UARTDATA_UARTTXCSR_SET(1);
uart_reg_write(UARTDATA_ADDRESS, rdata);
}
void
ar7240_sys_frequency(u32 *cpu_freq, u32 *ddr_freq, u32 *ahb_freq)
{
#ifdef CONFIG_HORNET_EMU
#ifdef CONFIG_HORNET_EMU_HARDI_WLAN
*cpu_freq = 48 * 1000000;
*ddr_freq = 48 * 1000000;
*ahb_freq = 24 * 1000000;
#else
*cpu_freq = 80 * 1000000;
*ddr_freq = 80 * 1000000;
*ahb_freq = 40 * 1000000;
#endif
#else
u32 ref_clock_rate, pll_freq;
u32 pllreg, clockreg;
u32 nint, refdiv, outdiv;
u32 cpu_div, ahb_div, ddr_div;
if ( ar7240_reg_rd(HORNET_BOOTSTRAP_STATUS) & HORNET_BOOTSTRAP_SEL_25M_40M_MASK )
ref_clock_rate = 40 * 1000000;
else
ref_clock_rate = 25 * 1000000;
pllreg = ar7240_reg_rd(AR7240_CPU_PLL_CONFIG);
clockreg = ar7240_reg_rd(AR7240_CPU_CLOCK_CONTROL);
if (clockreg & HORNET_CLOCK_CONTROL_BYPASS_MASK) {
/* Bypass PLL */
pll_freq = ref_clock_rate;
cpu_div = ahb_div = ddr_div = 1;
}
else {
nint = (pllreg & HORNET_PLL_CONFIG_NINT_MASK) >> HORNET_PLL_CONFIG_NINT_SHIFT;
refdiv = (pllreg & HORNET_PLL_CONFIG_REFDIV_MASK) >> HORNET_PLL_CONFIG_REFDIV_SHIFT;
outdiv = (pllreg & HORNET_PLL_CONFIG_OUTDIV_MASK) >> HORNET_PLL_CONFIG_OUTDIV_SHIFT;
pll_freq = (ref_clock_rate / refdiv) * nint;
if (outdiv == 1)
pll_freq /= 2;
else if (outdiv == 2)
pll_freq /= 4;
else if (outdiv == 3)
pll_freq /= 8;
else if (outdiv == 4)
pll_freq /= 16;
else if (outdiv == 5)
pll_freq /= 32;
else if (outdiv == 6)
pll_freq /= 64;
else if (outdiv == 7)
pll_freq /= 128;
else /* outdiv == 0 --> illegal value */
pll_freq /= 2;
cpu_div = (clockreg & HORNET_CLOCK_CONTROL_CPU_POST_DIV_MASK) >> HORNET_CLOCK_CONTROL_CPU_POST_DIV_SHIFT;
ddr_div = (clockreg & HORNET_CLOCK_CONTROL_DDR_POST_DIV_MASK) >> HORNET_CLOCK_CONTROL_DDR_POST_DIV_SFIFT;
ahb_div = (clockreg & HORNET_CLOCK_CONTROL_AHB_POST_DIV_MASK) >> HORNET_CLOCK_CONTROL_AHB_POST_DIV_SFIFT;
/*
* b00 : div by 1, b01 : div by 2, b10 : div by 3, b11 : div by 4
*/
cpu_div++;
ddr_div++;
ahb_div++;
}
*cpu_freq = pll_freq / cpu_div;
*ddr_freq = pll_freq / ddr_div;
*ahb_freq = pll_freq / ahb_div;
#endif
}
int serial_init(void)
{
u32 rdata;
u32 baudRateDivisor, clock_step;
u32 fcEnable = 0;
u32 ahb_freq, ddr_freq, cpu_freq;
ar7240_sys_frequency(&cpu_freq, &ddr_freq, &ahb_freq);
/* GPIO Configuration */
ar7240_reg_wr(AR7240_GPIO_OE, 0xcff);
rdata = ar7240_reg_rd(AR7240_GPIO_OUT);
rdata |= 0x400; // GPIO 10 (UART_SOUT) must output 1
ar7240_reg_wr(AR7240_GPIO_OUT, rdata);
rdata = ar7240_reg_rd(AR7240_GPIO_FUNC);
/* GPIO_FUN, bit1/UART_EN, bit2/UART_RTS_CTS_EN, bit15(disable_s26_uart) */
rdata |= (0x3<<1)|(0x1<<15);
ar7240_reg_wr(AR7240_GPIO_FUNC, rdata);
/* Get reference clock rate, then set baud rate to 115200 */
#ifndef CONFIG_HORNET_EMU
rdata = ar7240_reg_rd(HORNET_BOOTSTRAP_STATUS);
rdata &= HORNET_BOOTSTRAP_SEL_25M_40M_MASK;
if (rdata)
baudRateDivisor = ( 40000000 / (16*115200) ) - 1; // 40 MHz clock is taken as UART clock
else
baudRateDivisor = ( 25000000 / (16*115200) ) - 1; // 25 MHz clock is taken as UART clock
#else
baudRateDivisor = ( ahb_freq / (16*115200) ) - 1; // 40 MHz clock is taken as UART clock
#endif
clock_step = 8192;
rdata = UARTCLOCK_UARTCLOCKSCALE_SET(baudRateDivisor) | UARTCLOCK_UARTCLOCKSTEP_SET(clock_step);
uart_reg_write(UARTCLOCK_ADDRESS, rdata);
/* Config Uart Controller */
#if 1 /* No interrupt */
rdata = UARTCS_UARTDMAEN_SET(0) | UARTCS_UARTHOSTINTEN_SET(0) | UARTCS_UARTHOSTINT_SET(0)
| UARTCS_UARTSERIATXREADY_SET(0) | UARTCS_UARTTXREADYORIDE_SET(~fcEnable)
| UARTCS_UARTRXREADYORIDE_SET(~fcEnable) | UARTCS_UARTHOSTINTEN_SET(0);
#else
rdata = UARTCS_UARTDMAEN_SET(0) | UARTCS_UARTHOSTINTEN_SET(0) | UARTCS_UARTHOSTINT_SET(0)
| UARTCS_UARTSERIATXREADY_SET(0) | UARTCS_UARTTXREADYORIDE_SET(~fcEnable)
| UARTCS_UARTRXREADYORIDE_SET(~fcEnable) | UARTCS_UARTHOSTINTEN_SET(1);
#endif
/* is_dte == 1 */
rdata = rdata | UARTCS_UARTINTERFACEMODE_SET(2);
if (fcEnable) {
rdata = rdata | UARTCS_UARTFLOWCONTROLMODE_SET(2);
}
/* invert_fc ==0 (Inverted Flow Control) */
//rdata = rdata | UARTCS_UARTFLOWCONTROLMODE_SET(3);
/* parityEnable == 0 */
//rdata = rdata | UARTCS_UARTPARITYMODE_SET(2); -->Parity Odd
//rdata = rdata | UARTCS_UARTPARITYMODE_SET(3); -->Parity Even
uart_reg_write(UARTCS_ADDRESS, rdata);
return 0;
}
int serial_tstc (void)
{
return (UARTDATA_UARTRXCSR_GET(uart_reg_read(UARTDATA_ADDRESS)));
}
u8 serial_getc(void)
{
char ch_data;
while (!AthrUartGet(&ch_data)) ;
return (u8)ch_data;
}
void serial_putc(u8 byte)
{
if (byte == '\n') AthrUartPut('\r');
AthrUartPut((char)byte);
}
void serial_setbrg (void)
{
}
void serial_puts (const char *s)
{
while (*s)
{
serial_putc (*s++);
}
}
@@ -0,0 +1,562 @@
/*
* Memory controller config:
* Assumes that the caches are initialized.
*
* 0) Figah out the Tap controller settings.
* 1) Figure out whether the interface is 16bit or 32bit.
* 2) Size the DRAM
*
* 0) Tap controller settings
* --------------------------
* The Table below provides all possible values of TAP controllers. We need to
* find the extreme left and extreme right of the spectrum (of max_udelay and
* min_udelay). We then program the TAP to be in the middle.
* Note for this we would need to be able to read and write memory. So,
* initially we assume that a 16bit interface, which will always work unless
* there is exactly _1_ 32 bit part...for now we assume this is not the case.
*
* The algo:
* 0) Program the controller in 16bit mode.
* 1) Start with the extreme left of the table
* 2) Write 0xa4, 0xb5, 0xc6, 0xd7 to 0, 2, 4, 6
* 3) Read 0 - this will fetch the entire cacheline.
* 4) If the value at address 4 is good, record this table entry, goto 6
* 5) Increment to get the next table entry. Goto 2.
* 6) Start with extreme right. Do the same as above.
*
* 1) 16bit or 32bit
* -----------------
* 31st bit of reg 0x1800_0000 will determine the mode. By default,
* controller is set to 32-bit mode. In 32 bit mode, full data bus DQ [31:0]
* will be used to write 32 bit data. Suppose you have 16bit DDR memory
* (it will have 16bit wide data bus). If you try to write 16 bit DDR in 32
* bit mode, you are going to miss upper 16 bits of data. Reading to that
* location will give you only lower 16 bits correctly, upper 16 bits will
* have some junk value. E.g.,
*
* write to 0x0000_0000 0x12345678
* write to 0x0000_1000 0x00000000 (just to discharge DQ[31:16] )
* read from 0x0000_0000
* if u see something like 0x0000_5678 (or XXXX_5678 but not equal to
* 0x12345678) - its a 16 bit interface
*
* 2) Size the DRAM
* -------------------
* DDR wraps around. Write a pattern to 0x0000_0000. Write an address
* pattern at 4M, 8M, 16M etc. and check when 0x0000_0000 gets overwritten.
*
*
* We can use #define's for all these addresses and patterns but its easier
* to see what's going on without :)
*/
#include <common.h>
#include <asm/addrspace.h>
#include "ar7240_soc.h"
#ifdef COMPRESSED_UBOOT
# define prmsg(...)
#else
# define prmsg printf
#endif
uint8_t tap_settings[] =
{0x40, 0x41, 0x10, 0x12, 0x13, 0x15, 0x1a, 0x1c, 0x1f, 0x2f, 0x3f};
uint16_t tap_pattern[] = {0xa5, 0xb6, 0xc7, 0xd8};
void
ar7240_ddr_tap_set(uint8_t set)
{
ar7240_reg_wr_nf(AR7240_DDR_TAP_CONTROL0, set);
ar7240_reg_wr_nf(AR7240_DDR_TAP_CONTROL1, set);
ar7240_reg_wr_nf(AR7240_DDR_TAP_CONTROL2, set);
ar7240_reg_wr_nf(AR7240_DDR_TAP_CONTROL3, set);
}
/*
* We check for size in 4M increments
*/
#define AR7240_DDR_SIZE_INCR (4*1024*1024)
int
ar7240_ddr_find_size(void)
{
uint8_t *p = (uint8_t *)KSEG1, pat = 0x77;
int i;
*p = pat;
for(i = 1; ; i++) {
*(p + i * AR7240_DDR_SIZE_INCR) = (uint8_t)(i);
if (*p != pat) {
break;
}
}
return (i*AR7240_DDR_SIZE_INCR);
}
#ifndef CONFIG_WASP
void
ar7240_ddr_initial_config(uint32_t refresh)
{
int ddr2 = 0,ddr_config;
int ddr_config2,ext_mod,ddr2_ext_mod;
int mod_val,mod_val_init;
prmsg("\nsri\n");
#if 0
ar7240_reg_wr(AR7240_RESET, AR7240_RESET_DDR);
udelay(10);
#endif
ddr2 = ((ar7240_reg_rd(0xb8050020) & 0x1) == 0);
#ifdef ENABLE_DYNAMIC_CONF
if(*(volatile int *)CFG_DDR_MAGIC_F == CFG_DDR_MAGIC){
ddr_config = CFG_DDR_CONFIG_VAL_F;
ddr_config2 = CFG_DDR_CONFIG2_VAL_F;
ext_mod = CFG_DDR_EXT_MODE_VAL_F;
ddr2_ext_mod = ext_mod;
}
else
#endif
{
#ifdef CONFIG_SUPPORT_AR7241
if (is_ar7241() || is_ar7242()) {
if (ddr2) {
prmsg("%s(%d): virian ddr2 init\n", __func__, __LINE__);
ddr_config = CFG_7241_DDR2_CONFIG_VAL;
ddr_config2 = CFG_7241_DDR2_CONFIG2_VAL;
ext_mod = CFG_7241_DDR2_EXT_MODE_VAL;
ddr2_ext_mod = CFG_DDR2_EXT_MODE_VAL;
mod_val_init = CFG_7241_DDR2_MODE_VAL_INIT;
mod_val = CFG_7241_DDR2_MODE_VAL;
} else {
prmsg("%s(%d): virian ddr1 init\n", __func__, __LINE__);
ddr_config = CFG_7241_DDR1_CONFIG_VAL;
ddr_config2 = CFG_7241_DDR1_CONFIG2_VAL;
ext_mod = CFG_7241_DDR1_EXT_MODE_VAL;
ddr2_ext_mod = CFG_DDR2_EXT_MODE_VAL;
mod_val_init = CFG_7241_DDR1_MODE_VAL_INIT;
mod_val = CFG_7241_DDR1_MODE_VAL;
}
}
else
#endif
{
prmsg("%s(%d): python ddr init\n", __func__, __LINE__);
ddr_config = CFG_DDR_CONFIG_VAL;
ddr_config2 = CFG_DDR_CONFIG2_VAL;
ext_mod = CFG_DDR_EXT_MODE_VAL;
#ifndef CONFIG_WASP_EMU
ddr2_ext_mod = CFG_DDR2_EXT_MODE_VAL;
#endif
mod_val_init = CFG_DDR_MODE_VAL_INIT;
mod_val = CFG_DDR_MODE_VAL;
}
}
if (ddr2) {
ar7240_reg_wr_nf(0xb800008c, 0xA59);
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x10);
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x20);
udelay(10);
}
ar7240_reg_wr_nf(AR7240_DDR_CONFIG, ddr_config);
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_CONFIG2, ddr_config2 | 0x80);
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x8);
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_MODE, mod_val_init);
udelay(1000);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x1);
udelay(10);
if (ddr2) {
ar7240_reg_wr_nf(AR7240_DDR_EXT_MODE, ddr2_ext_mod);
} else {
ar7240_reg_wr_nf(AR7240_DDR_EXT_MODE, ext_mod);
}
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x2);
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x8);
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_MODE, mod_val);
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x1);
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_REFRESH, refresh);
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_RD_DATA_THIS_CYCLE,
CFG_DDR_RD_DATA_THIS_CYCLE_VAL);
udelay(100);
}
#else
int /* ram type */
wasp_ddr_initial_config(uint32_t refresh)
{
#if !defined(CONFIG_ATH_NAND_BR)
int ddr_config=0, ddr_config2=0, ext_mod, mod_val,
mod_val_init, cycle_val=0, tap_val=0, type=1;
uint32_t *pll = (unsigned *)PLL_CONFIG_VAL_F;
//prmsg("\nsri\n");
prmsg("Wasp 1.%d ", ar7240_reg_rd(AR7240_REV_ID) & 0xf);
switch(WASP_RAM_TYPE(ar7240_reg_rd(WASP_BOOTSTRAP_REG))) {
case 0:
case 1: // SDRAM
/*
XXX XXX XXX XXX XXX XXX XXX XXX XXX
Boot strap select is not working. In some boards,
ddr2 shows up as sdram. Hence ignoring the foll.
break statement.
XXX XXX XXX XXX XXX XXX XXX XXX XXX
break;
*/
//prmsg("%s(%d): Wasp sdram\n", __func__, __LINE__);
prmsg("SDRAM ");
ddr_config = CFG_934X_SDRAM_CONFIG_VAL;
ddr_config2 = CFG_934X_SDRAM_CONFIG2_VAL;
mod_val_init = CFG_934X_SDRAM_MODE_VAL_INIT;
mod_val = CFG_934X_SDRAM_MODE_VAL;
cycle_val = CFG_SDRAM_RD_DATA_THIS_CYCLE_VAL;
tap_val = CFG_934X_SDRAM_TAP_VAL;
ar7240_reg_wr_nf(AR7240_DDR_CTL_CONFIG, 0x13b);
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_DEBUG_RD_CNTL, 0x3000001f);
udelay(100);
type = 0;
break;
case 2: // ddr2
ddr_config = CFG_934X_DDR2_CONFIG_VAL;
ddr_config2 = CFG_934X_DDR2_CONFIG2_VAL;
ext_mod = CFG_934X_DDR2_EXT_MODE_VAL;
mod_val_init = CFG_934X_DDR2_MODE_VAL_INIT;
mod_val = CFG_934X_DDR2_MODE_VAL;
cycle_val = CFG_DDR2_RD_DATA_THIS_CYCLE_VAL;
tap_val = CFG_934X_DDR2_TAP_VAL;
//prmsg("%s(%d): (", __func__, __LINE__);
prmsg("DDR2 ");
if (ar7240_reg_rd(AR7240_REV_ID) & 0xf) {
/* NAND Clear */
if (ar7240_reg_rd(WASP_BOOTSTRAP_REG) & (1 << 3)) {
prmsg("32");
cycle_val = CFG_DDR2_RD_DATA_THIS_CYCLE_VAL_32;
ar7240_reg_wr_nf(AR7240_DDR_CTL_CONFIG, (1 << 6));
} else {
prmsg("16");
cycle_val = CFG_DDR2_RD_DATA_THIS_CYCLE_VAL_16;
ar7240_reg_rmw_set(AR7240_DDR_CTL_CONFIG, (1 << 6));
ar7240_reg_rmw_clear(AR7240_DDR_CTL_CONFIG, (0xf << 2));
}
} else {
#if DDR2_32BIT_SUPPORT
prmsg("32");
ar7240_reg_wr_nf(AR7240_DDR_CTL_CONFIG, 0);
#else
prmsg("16");
#endif
}
//prmsg("bit) ddr2 init\n");
prmsg("bit ");
udelay(10);
type = 1;
break;
case 3: // ddr1
//prmsg("%s(%d): Wasp (16bit) ddr1 init\n", __func__, __LINE__);
prmsg("DDR1 16bit ");
ddr_config = CFG_934X_DDR1_CONFIG_VAL;
ddr_config2 = CFG_934X_DDR1_CONFIG2_VAL;
ext_mod = CFG_934X_DDR1_EXT_MODE_VAL;
mod_val_init = CFG_934X_DDR1_MODE_VAL_INIT;
mod_val = CFG_934X_DDR1_MODE_VAL;
cycle_val = CFG_DDR1_RD_DATA_THIS_CYCLE_VAL;
tap_val = CFG_934X_DDR1_TAP_VAL;
type = 2;
break;
}
#if 0
if (*pll == PLL_MAGIC) {
uint32_t cas = pll[5];
if (cas == 3 || cas == 4) {
cas = (cas * 2) + 1;
ddr_config &= ~(DDR_CONFIG_CAS_LATENCY_MSB_MASK |
DDR_CONFIG_CAS_LATENCY_MASK);
ddr_config |= DDR_CONFIG_CAS_LATENCY_SET(cas & 0x7) |
DDR_CONFIG_CAS_LATENCY_MSB_SET((cas >> 3) & 1);
cas = pll[5];
ddr_config2 &= ~DDR_CONFIG2_GATE_OPEN_LATENCY_MASK;
ddr_config2 |= DDR_CONFIG2_GATE_OPEN_LATENCY_SET(2 * cas);
if (type == 1) {
uint32_t tmp;
tmp = ar7240_reg_rd(AR7240_DDR_DDR2_CONFIG);
tmp &= ~DDR2_CONFIG_DDR2_TWL_MASK;
tmp |= DDR2_CONFIG_DDR2_TWL_SET(cas == 3 ? 3 : 5);
ar7240_reg_wr_nf(AR7240_DDR_DDR2_CONFIG, tmp);
}
mod_val = (cas == 3 ? 0x33 : 0x43);
mod_val_init = 0x100 | mod_val;
}
}
#else
if (*pll == PLL_MAGIC) {
uint32_t cas = pll[5];
if (cas == 3 || cas == 4) {
cas = (cas * 2) + 2;
ddr_config &= ~(DDR_CONFIG_CAS_LATENCY_MSB_MASK |
DDR_CONFIG_CAS_LATENCY_MASK);
ddr_config |= DDR_CONFIG_CAS_LATENCY_SET(cas & 0x7) |
DDR_CONFIG_CAS_LATENCY_MSB_SET((cas >> 3) & 1);
cas = pll[5];
ddr_config2 &= ~DDR_CONFIG2_GATE_OPEN_LATENCY_MASK;
ddr_config2 |= DDR_CONFIG2_GATE_OPEN_LATENCY_SET((2 * cas) + 1);
if (type == 1) {
uint32_t tmp;
tmp = ar7240_reg_rd(AR7240_DDR_DDR2_CONFIG);
tmp &= ~DDR2_CONFIG_DDR2_TWL_MASK;
tmp |= DDR2_CONFIG_DDR2_TWL_SET(cas == 3 ? 3 : 5);
ar7240_reg_wr_nf(AR7240_DDR_DDR2_CONFIG, tmp);
}
mod_val = (cas == 3 ? 0x33 : 0x43);
mod_val_init = 0x100 | mod_val;
}
}
#endif
ar7240_reg_wr_nf(AR7240_DDR_RD_DATA_THIS_CYCLE, cycle_val);
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_BURST, 0x74444444);
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_BURST2, 0x222);
udelay(100);
ar7240_reg_wr_nf(AR7240_AHB_MASTER_TIMEOUT, 0xfffff);
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_CONFIG, ddr_config);
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_CONFIG2, ddr_config2);
udelay(100);
if (type == 1) {
ar7240_reg_wr_nf(AR7240_DDR_DDR2_CONFIG, CFG_934X_DDR2_EN_TWL_VAL);
udelay(100);
}
ar7240_reg_wr_nf(AR7240_DDR_CONFIG2, ddr_config2 | 0x80); // CKE enable
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x8); // Precharge
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x8); // Precharge
udelay(10);
if (type == 1) {
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x10); // EMR2
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x20); // EMR3
udelay(10);
}
if (type != 0) {
ar7240_reg_wr_nf(AR7240_DDR_EXT_MODE, 0x2);
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x2); // EMR DLL enable
udelay(10);
}
ar7240_reg_wr_nf(AR7240_DDR_MODE, mod_val_init);
udelay(1000);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x1); // MR Write
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x8); // Precharge
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x8); // Precharge
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x4); // Auto Refresh
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x4); // Auto Refresh
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_MODE, mod_val);
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x1); // MR Write
udelay(10);
if (type == 1) {
ar7240_reg_wr_nf(AR7240_DDR_EXT_MODE, CFG_934X_DDR2_EXT_MODE_VAL_INIT);
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x2); // EMR write
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_EXT_MODE, CFG_934X_DDR2_EXT_MODE_VAL);
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x2); // EMR write
udelay(100);
}
ar7240_reg_wr_nf(AR7240_DDR_REFRESH, refresh);
udelay(100);
ar7240_reg_wr (AR7240_DDR_TAP_CONTROL0, tap_val);
ar7240_reg_wr (AR7240_DDR_TAP_CONTROL1, tap_val);
if (ar7240_reg_rd(AR7240_REV_ID) & 0xf) {
/* NAND Clear */
if ((ar7240_reg_rd(WASP_BOOTSTRAP_REG) & (1 << 3)) && type) {
ar7240_reg_wr (AR7240_DDR_TAP_CONTROL2, tap_val);
ar7240_reg_wr (AR7240_DDR_TAP_CONTROL3, tap_val);
}
} else {
#if DDR2_32BIT_SUPPORT
if (type != 0) {
ar7240_reg_wr (AR7240_DDR_TAP_CONTROL2, tap_val);
ar7240_reg_wr (AR7240_DDR_TAP_CONTROL3, tap_val);
}
#endif
}
//prmsg("%s(%d): Wasp ddr init done\n", __func__, __LINE__);
#if (CFG_PLL_FREQ == CFG_PLL_600_500_250) || \
(CFG_PLL_FREQ == CFG_PLL_500_500_250)
// PMU2 ddr ldo tune
ar7240_reg_rmw_set(0xb8116c44, (0x3 << 19));
udelay(100);
#endif
return type;
#else
return 0;
#endif
}
#endif
#ifdef CONFIG_HORNET_EMU
void
ar7240_ddr_initial_config_for_fpga(void)
{
#ifdef CONFIG_HORNET_EMU_HARDI
/* HARDI FPGA board */
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x4); /* Auto-Refresh */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_REFRESH, 0x4100);
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONFIG, 0x7fd68cd0); /* Cas Latency 7 */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONFIG2, 0x959ec6a8); /* Gate Open 5 */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_DDR2_CONFIG, 0x858); /* Disable DDR2, set Write Latency */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x8); /* precharge all */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x8); /* precharge all */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x1); /* MR update */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_MODE, 0x133); /* Mode Word Settings */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_EXT_MODE, 0x0); /* Extended Mode Word Settings */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_RD_DATA_THIS_CYCLE, 0xff); /* DDR read data capture bit mask */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x1); /* MR update */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x2); /* EMR update */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x8); /* precharge all */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x8); /* precharge all */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x4); /* Auto-Refresh */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x4); /* Auto-Refresh */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_MODE, 0x133); /* Mode Word Settings */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x1); /* MR update */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_EXT_MODE, 0x382); /* Extended Mode Word Settings */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x2); /* EMR update */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_EXT_MODE, 0x402); /* Extended Mode Word Settings */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x2); /* EMR update */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_MODE, 0x33); /* Mode Word Settings */
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x1); /* MR update */
udelay(10);
#ifdef CONFIG_HORNET_EMU_HARDI_WLAN
/*
* Emulation board reference clock is 48 MHz(20.833ns)
* DDR request 64ms has 8192 refresh
* So each refresh interval is 64ms/8192 = 7812.5 ns
* i.e ddr have to refresh in 7812.5/20.833 = 375 = 0x177 clock cycles
*/
ar7240_reg_wr_nf(AR7240_DDR_REFRESH, 0x4177);
#else
/*
* Emulation board reference clock is 80 MHz(12.5ns)
* DDR request 64ms has 8192 refresh
* So each refresh interval is 64ms/8192 = 7812.5 ns
* i.e ddr have to refresh in 7812.5/12.5 = 625 = 0x271 clock cycles
*/
ar7240_reg_wr_nf(AR7240_DDR_REFRESH, 0x4271);
#endif
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_TAP_CONTROL0, 0x0);
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_TAP_CONTROL1, 0x0);
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_TAP_CONTROL2, 0x0);
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_TAP_CONTROL3, 0x0);
udelay(10);
#else
/* EBU FPGA board */
ar7240_reg_wr_nf(AR7240_DDR_CONFIG, 0xc7bc8cd0); /* Cas Latency 8 */
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_CONFIG2, 0x95d0e6a8); /* Gate Open 5 */
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x8);
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_MODE, 0x123);
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x1);
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_EXT_MODE, 0x1);
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x2);
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x8);
udelay(10);
ar7240_reg_wr_nf(AR7240_DDR_MODE, 0x23);
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_CONTROL, 0x1);
udelay(10);
/*
* Emulation board reference clock is 80 MHz(12.5ns)
* DDR request 64ms has 8192 refresh
* So each refresh interval is 64ms/8192 = 7812.5 ns
* i.e ddr have to refresh in 7812.5/12.5 = 625 = 0x271 clock cycles
*/
ar7240_reg_wr_nf(AR7240_DDR_REFRESH, 0x4271);
udelay(100);
ar7240_reg_wr_nf(AR7240_DDR_RD_DATA_THIS_CYCLE, 0x00ff);
udelay(100);
#endif
}
#endif