From 0775437293a6963cb21244dfae6978cbf67c6bfe Mon Sep 17 00:00:00 2001 From: Ben Warren Date: Wed, 21 Oct 2009 21:53:39 -0700 Subject: Fix DM9000 MAC address handling Proper behavior is to pull MAC address from NVRAM in the initialization() an stuff it in dev->address, then program the device from dev->address in the init() function. Signed-off-by: Ben Warren --- drivers/net/dm9000x.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dm9000x.c b/drivers/net/dm9000x.c index efe913589..73dd33572 100644 --- a/drivers/net/dm9000x.c +++ b/drivers/net/dm9000x.c @@ -284,7 +284,6 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd) int i, oft, lnk; u8 io_mode; struct board_info *db = &dm9000_info; - uchar enetaddr[6]; DM9000_DBG("%s\n", __func__); @@ -342,20 +341,11 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd) /* Clear interrupt status */ DM9000_iow(DM9000_ISR, ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS); - /* Set Node address */ - if (!eth_getenv_enetaddr("ethaddr", enetaddr)) { -#if !defined(CONFIG_DM9000_NO_SROM) - for (i = 0; i < 3; i++) - dm9000_read_srom_word(i, enetaddr + 2 * i); - eth_setenv_enetaddr("ethaddr", enetaddr); -#endif - } - - printf("MAC: %pM\n", enetaddr); + printf("MAC: %pM\n", dev->enetaddr); /* fill device MAC address registers */ for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++) - DM9000_iow(oft, enetaddr[i]); + DM9000_iow(oft, dev->enetaddr[i]); for (i = 0, oft = 0x16; i < 8; i++, oft++) DM9000_iow(oft, 0xff); @@ -558,6 +548,15 @@ void dm9000_write_srom_word(int offset, u16 val) } #endif +static void dm9000_get_enetaddr(struct eth_device *dev) +{ +#if !defined(CONFIG_DM9000_NO_SROM) + int i; + for (i = 0; i < 3; i++) + dm9000_read_srom_word(i, dev->enetaddr + (2 * i)); +#endif +} + /* Read a byte from I/O port */ @@ -621,6 +620,9 @@ int dm9000_initialize(bd_t *bis) { struct eth_device *dev = &(dm9000_info.netdev); + /* Load MAC address from EEPROM */ + dm9000_get_enetaddr(dev); + dev->init = dm9000_init; dev->halt = dm9000_halt; dev->send = dm9000_send; -- cgit v1.2.3 From 01471d538fb163f472a769f21267d7676c91267c Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 4 Nov 2009 01:29:04 -0600 Subject: Revert "ppc/85xx/pci: fsl_pci_init: pcie agent mode support" This reverts commit 70ed869ea5f6b1d13d7b140c83ec0dcd8a127ddc. There isn't any need to modify the API for fsl_pci_init_port to pass the status of host/agent(end-point) status. We can determine that internally to fsl_pci_init_port. Revert the patch that makes the API change. Signed-off-by: Kumar Gala --- board/freescale/mpc8572ds/mpc8572ds.c | 6 +++--- board/freescale/p1_p2_rdb/pci.c | 4 ++-- board/freescale/p2020ds/p2020ds.c | 6 +++--- board/sbc8548/sbc8548.c | 4 ++-- drivers/pci/fsl_pci_init.c | 18 ++---------------- include/asm-ppc/fsl_pci.h | 3 +-- 6 files changed, 13 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/board/freescale/mpc8572ds/mpc8572ds.c b/board/freescale/mpc8572ds/mpc8572ds.c index 2b3223453..933dd127e 100644 --- a/board/freescale/mpc8572ds/mpc8572ds.c +++ b/board/freescale/mpc8572ds/mpc8572ds.c @@ -199,7 +199,7 @@ void pci_init_board(void) pcie_ep ? "End Point" : "Root Complex", pci_info[num].regs); first_free_busno = fsl_pci_init_port(&pci_info[num++], - &pcie3_hose, first_free_busno, pcie_ep); + &pcie3_hose, first_free_busno); /* * Activate ULI1575 legacy chip by performing a fake * memory access. Needed to make ULI RTC work. @@ -231,7 +231,7 @@ void pci_init_board(void) pcie_ep ? "End Point" : "Root Complex", pci_info[num].regs); first_free_busno = fsl_pci_init_port(&pci_info[num++], - &pcie2_hose, first_free_busno, pcie_ep); + &pcie2_hose, first_free_busno); } else { printf (" PCIE2: disabled\n"); } @@ -251,7 +251,7 @@ void pci_init_board(void) pcie_ep ? "End Point" : "Root Complex", pci_info[num].regs); first_free_busno = fsl_pci_init_port(&pci_info[num++], - &pcie1_hose, first_free_busno, pcie_ep); + &pcie1_hose, first_free_busno); } else { printf (" PCIE1: disabled\n"); } diff --git a/board/freescale/p1_p2_rdb/pci.c b/board/freescale/p1_p2_rdb/pci.c index 773659673..4c08f9efa 100644 --- a/board/freescale/p1_p2_rdb/pci.c +++ b/board/freescale/p1_p2_rdb/pci.c @@ -71,7 +71,7 @@ void pci_init_board(void) pcie_ep ? "End Point" : "Root Complex", pci_info[num].regs); first_free_busno = fsl_pci_init_port(&pci_info[num++], - &pcie2_hose, first_free_busno, pcie_ep); + &pcie2_hose, first_free_busno); } else { printf (" PCIE2: disabled\n"); } @@ -90,7 +90,7 @@ void pci_init_board(void) pcie_ep ? "End Point" : "Root Complex", pci_info[num].regs); first_free_busno = fsl_pci_init_port(&pci_info[num++], - &pcie1_hose, first_free_busno, pcie_ep); + &pcie1_hose, first_free_busno); } else { printf (" PCIE1: disabled\n"); } diff --git a/board/freescale/p2020ds/p2020ds.c b/board/freescale/p2020ds/p2020ds.c index 9878fba10..e38c0145e 100644 --- a/board/freescale/p2020ds/p2020ds.c +++ b/board/freescale/p2020ds/p2020ds.c @@ -227,7 +227,7 @@ void pci_init_board(void) pcie_ep ? "End Point" : "Root Complex", pci_info[num].regs); first_free_busno = fsl_pci_init_port(&pci_info[num++], - &pcie2_hose, first_free_busno, pcie_ep); + &pcie2_hose, first_free_busno); /* * The workaround doesn't work on p2020 because the location @@ -267,7 +267,7 @@ void pci_init_board(void) pcie_ep ? "End Point" : "Root Complex", pci_info[num].regs); first_free_busno = fsl_pci_init_port(&pci_info[num++], - &pcie3_hose, first_free_busno, pcie_ep); + &pcie3_hose, first_free_busno); } else { printf(" PCIE3: disabled\n"); } @@ -286,7 +286,7 @@ void pci_init_board(void) pcie_ep ? "End Point" : "Root Complex", pci_info[num].regs); first_free_busno = fsl_pci_init_port(&pci_info[num++], - &pcie1_hose, first_free_busno, pcie_ep); + &pcie1_hose, first_free_busno); } else { printf(" PCIE1: disabled\n"); } diff --git a/board/sbc8548/sbc8548.c b/board/sbc8548/sbc8548.c index 5e3e17658..194f6ab96 100644 --- a/board/sbc8548/sbc8548.c +++ b/board/sbc8548/sbc8548.c @@ -359,7 +359,7 @@ pci_init_board(void) SET_STD_PCI_INFO(pci_info[num], 1); first_free_busno = fsl_pci_init_port(&pci_info[num++], - &pci1_hose, first_free_busno, 0); + &pci1_hose, first_free_busno); } else { printf (" PCI: disabled\n"); } @@ -378,7 +378,7 @@ pci_init_board(void) SET_STD_PCIE_INFO(pci_info[num], 1); printf (" PCIE at base address %lx\n", pci_info[num].regs); first_free_busno = fsl_pci_init_port(&pci_info[num++], - &pcie1_hose, first_free_busno, 0); + &pcie1_hose, first_free_busno); } else { printf (" PCIE: disabled\n"); } diff --git a/drivers/pci/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c index 8fbab68a2..87944bfad 100644 --- a/drivers/pci/fsl_pci_init.c +++ b/drivers/pci/fsl_pci_init.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2009 Freescale Semiconductor, Inc. + * Copyright 2007 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -413,27 +413,13 @@ void fsl_pci_init(struct pci_controller *hose, u32 cfg_addr, u32 cfg_data) } int fsl_pci_init_port(struct fsl_pci_info *pci_info, - struct pci_controller *hose, int busno, int pcie_ep) + struct pci_controller *hose, int busno) { volatile ccsr_fsl_pci_t *pci; struct pci_region *r; pci = (ccsr_fsl_pci_t *) pci_info->regs; - if (pcie_ep) { - volatile pit_t *pi = &pci->pit[2]; - - pci_setup_indirect(hose, (u32)&pci->cfg_addr, - (u32)&pci->cfg_data); - out_be32(&pi->pitar, 0); - out_be32(&pi->piwbar, 0); - out_be32(&pi->piwar, PIWAR_EN | PIWAR_LOCAL | - PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP | PIWAR_IWS_4K); - - fsl_pci_config_unlock(hose); - return 0; - } - /* on non-PCIe controllers we don't have pme_msg_det so this code * should do nothing since the read will return 0 */ diff --git a/include/asm-ppc/fsl_pci.h b/include/asm-ppc/fsl_pci.h index 6b0c89bd3..2790da7ed 100644 --- a/include/asm-ppc/fsl_pci.h +++ b/include/asm-ppc/fsl_pci.h @@ -62,7 +62,6 @@ typedef struct pci_inbound_window { #define PIWAR_LOCAL 0x00f00000 #define PIWAR_READ_SNOOP 0x00050000 #define PIWAR_WRITE_SNOOP 0x00005000 -#define PIWAR_IWS_4K 0x0000000b u32 res2[3]; } pit_t; @@ -172,7 +171,7 @@ struct fsl_pci_info { }; int fsl_pci_init_port(struct fsl_pci_info *pci_info, - struct pci_controller *hose, int busno, int pcie_ep); + struct pci_controller *hose, int busno); #define SET_STD_PCI_INFO(x, num) \ { \ -- cgit v1.2.3 From 715d8f7608f77c93f1807a032644893fd5b6d08b Mon Sep 17 00:00:00 2001 From: Ed Swarthout Date: Mon, 2 Nov 2009 09:05:49 -0600 Subject: fsl_pci_init_port end-point initialization is broken commit 70ed869e broke fsl pcie end-point initialization. Returning 0 is not correct. The function must return the first free bus number for the next controller. fsl_pci_init() must still be called and a bus allocated even if the controller is an end-point. Signed-off-by: Ed Swarthout Acked-by: Vivek Mahajan Signed-off-by: Kumar Gala --- drivers/pci/fsl_pci_init.c | 18 +++++++++++++++++- include/asm-ppc/fsl_pci.h | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c index 87944bfad..170cc257c 100644 --- a/drivers/pci/fsl_pci_init.c +++ b/drivers/pci/fsl_pci_init.c @@ -1,5 +1,5 @@ /* - * Copyright 2007 Freescale Semiconductor, Inc. + * Copyright 2007-2009 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -42,6 +42,7 @@ DECLARE_GLOBAL_DATA_PTR; #define FSL_PCI_PBFR 0x44 #define FSL_PCIE_CAP_ID 0x4c #define FSL_PCIE_CFG_RDY 0x4b0 +#define FSL_PROG_IF_AGENT 0x1 void pciauto_prescan_setup_bridge(struct pci_controller *hose, pci_dev_t dev, int sub_bus); @@ -412,6 +413,16 @@ void fsl_pci_init(struct pci_controller *hose, u32 cfg_addr, u32 cfg_data) } } +int fsl_is_pci_agent(struct pci_controller *hose) +{ + u8 prog_if; + pci_dev_t dev = PCI_BDF(hose->first_busno, 0, 0); + + pci_hose_read_config_byte(hose, dev, PCI_CLASS_PROG, &prog_if); + + return (prog_if == FSL_PROG_IF_AGENT); +} + int fsl_pci_init_port(struct fsl_pci_info *pci_info, struct pci_controller *hose, int busno) { @@ -450,6 +461,11 @@ int fsl_pci_init_port(struct fsl_pci_info *pci_info, fsl_pci_init(hose, (u32)&pci->cfg_addr, (u32)&pci->cfg_data); + if (fsl_is_pci_agent(hose)) { + fsl_pci_config_unlock(hose); + hose->last_busno = hose->first_busno; + } + printf(" PCIE%x on bus %02x - %02x\n", pci_info->pci_num, hose->first_busno, hose->last_busno); diff --git a/include/asm-ppc/fsl_pci.h b/include/asm-ppc/fsl_pci.h index 2790da7ed..a5f72f5cd 100644 --- a/include/asm-ppc/fsl_pci.h +++ b/include/asm-ppc/fsl_pci.h @@ -25,6 +25,7 @@ int is_fsl_pci_agent(enum law_trgt_if trgt, u32 host_agent); int is_fsl_pci_cfg(enum law_trgt_if trgt, u32 io_sel); +int fsl_is_pci_agent(struct pci_controller *hose); void fsl_pci_init(struct pci_controller *hose, u32 cfg_addr, u32 cfg_data); void fsl_pci_config_unlock(struct pci_controller *hose); void ft_fsl_pci_setup(void *blob, const char *pci_alias, -- cgit v1.2.3 From 497ab0eec5e1e2dfccc141a4485cd6b940e1424a Mon Sep 17 00:00:00 2001 From: "Hui.Tang" Date: Thu, 5 Nov 2009 09:58:44 +0800 Subject: Fix cs8900 dev->priv not init issue Ensure all CS8900 data structures are assigned before accessing device Signed-off-by: Hui.Tang Signed-off-by: Ben Warren --- drivers/net/cs8900.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/cs8900.c b/drivers/net/cs8900.c index 587f7f62a..a9d1f2273 100644 --- a/drivers/net/cs8900.c +++ b/drivers/net/cs8900.c @@ -321,15 +321,16 @@ int cs8900_initialize(u8 dev_num, int base_addr) memset(priv, 0, sizeof(*priv)); priv->regs = (struct cs8900_regs *)base_addr; - /* Load MAC address from EEPROM */ - cs8900_get_enetaddr(dev); - dev->iobase = base_addr; dev->priv = priv; dev->init = cs8900_init; dev->halt = cs8900_halt; dev->send = cs8900_send; dev->recv = cs8900_recv; + + /* Load MAC address from EEPROM */ + cs8900_get_enetaddr(dev); + sprintf(dev->name, "%s-%hu", CS8900_DRIVERNAME, dev_num); eth_register(dev); -- cgit v1.2.3 From 830c7b6722c6a9762411bf52a7bf2fae4dc71dab Mon Sep 17 00:00:00 2001 From: Ben Warren Date: Mon, 9 Nov 2009 11:43:18 -0800 Subject: Fix CS8900 regression on impa7 board The following error was seen on impa7 board, due to its use of a 32-bit bus on CS8900. cs8900.c:137:37: error: macro "get_reg_init_bus" passed 2 arguments, but takes just 1 This patch gives the macro the correct number of arguments Signed-off-by: Ben Warren --- drivers/net/cs8900.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/cs8900.c b/drivers/net/cs8900.c index a9d1f2273..df360042b 100644 --- a/drivers/net/cs8900.c +++ b/drivers/net/cs8900.c @@ -56,7 +56,7 @@ #define REG_READ(a) readl((a)) /* we don't need 16 bit initialisation on 32 bit bus */ -#define get_reg_init_bus(x) get_reg((x)) +#define get_reg_init_bus(r,d) get_reg((r),(d)) #else -- cgit v1.2.3 From 1031ae960ce6ce8332190278a06e2d72c2b2793e Mon Sep 17 00:00:00 2001 From: Ben Warren Date: Mon, 9 Nov 2009 14:01:08 -0800 Subject: SMC91111: Clean up SMC_inx macros on xsengine and xaeniax This patch fixes the following warnings: Configuring for xaeniax board... smc91111_eeprom.c: In function 'print_macaddr': smc91111_eeprom.c:278: warning: suggest parentheses around + or - in operand of & smc91111_eeprom.c:281: warning: suggest parentheses around + or - in operand of & ... Configuring for xsengine board... smc91111_eeprom.c: In function 'print_macaddr': smc91111_eeprom.c:278: warning: suggest parentheses around + or - inside shift smc91111_eeprom.c:281: warning: suggest parentheses around + or - inside shift Signed-off-by: Ben Warren --- drivers/net/smc91111.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/smc91111.h b/drivers/net/smc91111.h index bb4524106..895c74978 100644 --- a/drivers/net/smc91111.h +++ b/drivers/net/smc91111.h @@ -81,10 +81,10 @@ struct smc91111_priv{ #ifdef CONFIG_PXA250 #ifdef CONFIG_XSENGINE -#define SMC_inl(a,r) (*((volatile dword *)((a)->iobase+(r<<1)))) -#define SMC_inw(a,r) (*((volatile word *)((a)->iobase+(r<<1)))) +#define SMC_inl(a,r) (*((volatile dword *)((a)->iobase+((r)<<1)))) +#define SMC_inw(a,r) (*((volatile word *)((a)->iobase+((r)<<1)))) #define SMC_inb(a,p) ({ \ - unsigned int __p = (unsigned int)((a)->iobase + (p<<1)); \ + unsigned int __p = (unsigned int)((a)->iobase + ((p)<<1)); \ unsigned int __v = *(volatile unsigned short *)((__p) & ~2); \ if (__p & 2) __v >>= 8; \ else __v &= 0xff; \ @@ -99,7 +99,7 @@ struct smc91111_priv{ __v; }) #define SMC_inb(a,p) ({ \ unsigned int ___v = SMC_inw((a),(p) & ~1); \ - if (p & 1) ___v >>= 8; \ + if ((p) & 1) ___v >>= 8; \ else ___v &= 0xff; \ ___v; }) #else -- cgit v1.2.3 From e8f1546a88b4ade6a910c4a7958a774ee1b40023 Mon Sep 17 00:00:00 2001 From: javier Martin Date: Thu, 29 Oct 2009 08:18:34 +0100 Subject: mxc_fec: fix some erroneous PHY accesses. This patch fixes erroneous access to the ethernet PHY which broke the driver. 1. Selector field in the auto-negotiation register must be 0x00001 for using 802.3, not 0x00000 which is reseved. 2. Access to the PHY address specified by CONFIG_FEC_MXC_PHYADDR, not 0x0 fixed address. This has been tested in i.MX27 Litekit board and eldk-4.2 toolchains. Now using proper defines for auto-negotiation register. Signed-off-by: Javier Martin Signed-off-by: Ben Warren --- drivers/net/fec_mxc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index bd83a249e..9764e1212 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -157,7 +157,9 @@ static int miiphy_restart_aneg(struct eth_device *dev) /* * Set the auto-negotiation advertisement register bits */ - miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, PHY_ANAR, 0x1e0); + miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, PHY_ANAR, + PHY_ANLPAR_TXFD | PHY_ANLPAR_TX | PHY_ANLPAR_10FD | + PHY_ANLPAR_10 | PHY_ANLPAR_PSB_802_3); miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, PHY_BMCR, PHY_BMCR_AUTON | PHY_BMCR_RST_NEG); @@ -341,8 +343,8 @@ static int fec_open(struct eth_device *edev) writel(FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl); miiphy_wait_aneg(edev); - miiphy_speed(edev->name, 0); - miiphy_duplex(edev->name, 0); + miiphy_speed(edev->name, CONFIG_FEC_MXC_PHYADDR); + miiphy_duplex(edev->name, CONFIG_FEC_MXC_PHYADDR); /* * Enable SmartDMA receive task -- cgit v1.2.3 From 651ef90fa6ca824c8e581aeef9e04bbbe7f7e9ce Mon Sep 17 00:00:00 2001 From: javier Martin Date: Thu, 29 Oct 2009 08:22:43 +0100 Subject: mxc_fec: avoid free() calls to already freed pointers. Sometimes, inside NetLoop, eth_halt() is called before eth_init() has been called. This is harmless except for free() calls to pointers which have not been allocated yet. This patch initializes those pointers to NULL and allocates them only the first time. This way we can get rid of free calls in halt callback. This has been tested in i.MX27 Litekit board and eldk-4.2 toolchains. Signed-off-by: Javier Martin Signed-off-by: Ben Warren --- drivers/net/fec_mxc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index 9764e1212..ad073077c 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -55,6 +55,8 @@ struct fec_priv gfec = { .tbd_base = NULL, .tbd_index = 0, .bd = NULL, + .rdb_ptr = NULL, + .base_ptr = NULL, }; /* @@ -230,7 +232,8 @@ static int fec_rbd_init(struct fec_priv *fec, int count, int size) uint32_t p = 0; /* reserve data memory and consider alignment */ - fec->rdb_ptr = malloc(size * count + DB_DATA_ALIGNMENT); + if (fec->rdb_ptr == NULL) + fec->rdb_ptr = malloc(size * count + DB_DATA_ALIGNMENT); p = (uint32_t)fec->rdb_ptr; if (!p) { puts("fec_imx27: not enough malloc memory!\n"); @@ -365,8 +368,9 @@ static int fec_init(struct eth_device *dev, bd_t* bd) * Datasheet forces the startaddress of each chain is 16 byte * aligned */ - fec->base_ptr = malloc((2 + FEC_RBD_NUM) * - sizeof(struct fec_bd) + DB_ALIGNMENT); + if (fec->base_ptr == NULL) + fec->base_ptr = malloc((2 + FEC_RBD_NUM) * + sizeof(struct fec_bd) + DB_ALIGNMENT); base = (uint32_t)fec->base_ptr; if (!base) { puts("fec_imx27: not enough malloc memory!\n"); @@ -493,8 +497,6 @@ static void fec_halt(struct eth_device *dev) writel(0, &fec->eth->ecntrl); fec->rbd_index = 0; fec->tbd_index = 0; - free(fec->rdb_ptr); - free(fec->base_ptr); debug("eth_halt: done\n"); } -- cgit v1.2.3 From fbd47b6753b08162436d9ccad1e63c8d43ede54c Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Thu, 12 Nov 2009 15:35:08 +0200 Subject: smc911x: make smc911x_initialize return correct value Make smc911x_initialize return -1 on error and number of interfaces detected otherwise. Signed-off-by: Mike Rapoport Acked-by: Mike Frysinger Signed-off-by: Ben Warren --- drivers/net/smc911x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index c50758e53..c027abe9f 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -243,7 +243,7 @@ int smc911x_initialize(u8 dev_num, int base_addr) dev = malloc(sizeof(*dev)); if (!dev) { free(dev); - return 0; + return -1; } memset(dev, 0, sizeof(*dev)); @@ -271,5 +271,5 @@ int smc911x_initialize(u8 dev_num, int base_addr) sprintf(dev->name, "%s-%hu", DRIVERNAME, dev_num); eth_register(dev); - return 0; + return 1; } -- cgit v1.2.3 From f2cea405f83da46b72098ea874fb3eefe185d312 Mon Sep 17 00:00:00 2001 From: Po-Yu Chuang Date: Wed, 23 Sep 2009 15:52:35 +0800 Subject: Add driver for FTRTC010 real time clock Signed-off-by: Po-Yu Chuang Edited commit message. Signed-off-by: Wolfgang Denk --- drivers/rtc/Makefile | 1 + drivers/rtc/ftrtc010.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 drivers/rtc/ftrtc010.c (limited to 'drivers') diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index ea7d899ea..772a49a90 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -40,6 +40,7 @@ COBJS-$(CONFIG_RTC_DS1556) += ds1556.o COBJS-$(CONFIG_RTC_DS164x) += ds164x.o COBJS-$(CONFIG_RTC_DS174x) += ds174x.o COBJS-$(CONFIG_RTC_DS3231) += ds3231.o +COBJS-$(CONFIG_RTC_FTRTC010) += ftrtc010.o COBJS-$(CONFIG_RTC_ISL1208) += isl1208.o COBJS-$(CONFIG_RTC_M41T11) += m41t11.o COBJS-$(CONFIG_RTC_M41T60) += m41t60.o diff --git a/drivers/rtc/ftrtc010.c b/drivers/rtc/ftrtc010.c new file mode 100644 index 000000000..c3c0bc2f5 --- /dev/null +++ b/drivers/rtc/ftrtc010.c @@ -0,0 +1,124 @@ +/* + * Faraday FTRTC010 Real Time Clock + * + * (C) Copyright 2009 Faraday Technology + * Po-Yu Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +struct ftrtc010 { + unsigned int sec; /* 0x00 */ + unsigned int min; /* 0x04 */ + unsigned int hour; /* 0x08 */ + unsigned int day; /* 0x0c */ + unsigned int alarm_sec; /* 0x10 */ + unsigned int alarm_min; /* 0x14 */ + unsigned int alarm_hour; /* 0x18 */ + unsigned int record; /* 0x1c */ + unsigned int cr; /* 0x20 */ +}; + +/* + * RTC Control Register + */ +#define FTRTC010_CR_ENABLE (1 << 0) +#define FTRTC010_CR_INTERRUPT_SEC (1 << 1) /* per second irq */ +#define FTRTC010_CR_INTERRUPT_MIN (1 << 2) /* per minute irq */ +#define FTRTC010_CR_INTERRUPT_HR (1 << 3) /* per hour irq */ +#define FTRTC010_CR_INTERRUPT_DAY (1 << 4) /* per day irq */ + +static struct ftrtc010 *rtc = (struct ftrtc010 *)CONFIG_FTRTC010_BASE; + +static void ftrtc010_enable (void) +{ + writel (FTRTC010_CR_ENABLE, &rtc->cr); +} + +/* + * return current time in seconds + */ +static unsigned long ftrtc010_time (void) +{ + unsigned long day; + unsigned long hour; + unsigned long minute; + unsigned long second; + unsigned long second2; + + do { + second = readl (&rtc->sec); + day = readl (&rtc->day); + hour = readl (&rtc->hour); + minute = readl (&rtc->min); + second2 = readl (&rtc->sec); + } while (second != second2); + + return day * 24 * 60 * 60 + hour * 60 * 60 + minute * 60 + second; +} + +/* + * Get the current time from the RTC + */ + +int rtc_get (struct rtc_time *tmp) +{ + unsigned long now; + + debug ("%s(): record register: %x\n", + __func__, readl (&rtc->record)); + + now = ftrtc010_time () + readl (&rtc->record); + + to_tm (now, tmp); + + return 0; +} + +/* + * Set the RTC + */ +int rtc_set (struct rtc_time *tmp) +{ + unsigned long new; + unsigned long now; + + debug ("%s(): DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + __func__, + tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + + new = mktime (tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_hour, + tmp->tm_min, tmp->tm_sec); + + now = ftrtc010_time (); + + debug ("%s(): write %lx to record register\n", __func__, new - now); + + writel (new - now, &rtc->record); + + return 0; +} + +void rtc_reset (void) +{ + debug ("%s()\n", __func__); + ftrtc010_enable (); +} -- cgit v1.2.3 From d394a7795027d96ca55799df40bd5c4a13dbeebe Mon Sep 17 00:00:00 2001 From: Jason McMullan Date: Fri, 9 Oct 2009 17:12:23 -0400 Subject: sf: new driver for Winbond W25X16/32/64 devices Signed-off-by: Jason McMullan Signed-off-by: Mike Frysinger --- drivers/mtd/spi/Makefile | 1 + drivers/mtd/spi/spi_flash.c | 5 + drivers/mtd/spi/spi_flash_internal.h | 1 + drivers/mtd/spi/winbond.c | 332 +++++++++++++++++++++++++++++++++++ 4 files changed, 339 insertions(+) create mode 100644 drivers/mtd/spi/winbond.c (limited to 'drivers') diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index e3e029280..4f11b3631 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -31,6 +31,7 @@ COBJS-$(CONFIG_SPI_FLASH_MACRONIX) += macronix.o COBJS-$(CONFIG_SPI_FLASH_SPANSION) += spansion.o COBJS-$(CONFIG_SPI_FLASH_SST) += sst.o COBJS-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.o +COBJS-$(CONFIG_SPI_FLASH_WINBOND) += winbond.o COBJS-$(CONFIG_SPI_M95XXX) += eeprom_m95xxx.o COBJS := $(COBJS-y) diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 25346a4a1..612f819dc 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -140,6 +140,11 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, flash = spi_flash_probe_macronix(spi, idcode); break; #endif +#ifdef CONFIG_SPI_FLASH_WINBOND + case 0xef: + flash = spi_flash_probe_winbond(spi, idcode); + break; +#endif #ifdef CONFIG_SPI_FLASH_STMICRO case 0x20: flash = spi_flash_probe_stmicro(spi, idcode); diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h index 0612383c6..08546fbb0 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -49,3 +49,4 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode); struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode); struct spi_flash *spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode); struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 *idcode); +struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode); diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c new file mode 100644 index 000000000..b8da92319 --- /dev/null +++ b/drivers/mtd/spi/winbond.c @@ -0,0 +1,332 @@ +/* + * Copyright 2008, Network Appliance Inc. + * Author: Jason McMullan netapp.com> + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include + +#include "spi_flash_internal.h" + +/* M25Pxx-specific commands */ +#define CMD_W25_WREN 0x06 /* Write Enable */ +#define CMD_W25_WRDI 0x04 /* Write Disable */ +#define CMD_W25_RDSR 0x05 /* Read Status Register */ +#define CMD_W25_WRSR 0x01 /* Write Status Register */ +#define CMD_W25_READ 0x03 /* Read Data Bytes */ +#define CMD_W25_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */ +#define CMD_W25_PP 0x02 /* Page Program */ +#define CMD_W25_SE 0x20 /* Sector (4K) Erase */ +#define CMD_W25_BE 0xd8 /* Block (64K) Erase */ +#define CMD_W25_CE 0xc7 /* Chip Erase */ +#define CMD_W25_DP 0xb9 /* Deep Power-down */ +#define CMD_W25_RES 0xab /* Release from DP, and Read Signature */ + +#define WINBOND_ID_W25X16 0x3015 +#define WINBOND_ID_W25X32 0x3016 +#define WINBOND_ID_W25X64 0x3017 + +#define WINBOND_SR_WIP (1 << 0) /* Write-in-Progress */ + +struct winbond_spi_flash_params { + uint16_t id; + /* Log2 of page size in power-of-two mode */ + uint8_t l2_page_size; + uint16_t pages_per_sector; + uint16_t sectors_per_block; + uint8_t nr_blocks; + const char *name; +}; + +/* spi_flash needs to be first so upper layers can free() it */ +struct winbond_spi_flash { + struct spi_flash flash; + const struct winbond_spi_flash_params *params; +}; + +static inline struct winbond_spi_flash * +to_winbond_spi_flash(struct spi_flash *flash) +{ + return container_of(flash, struct winbond_spi_flash, flash); +} + +static const struct winbond_spi_flash_params winbond_spi_flash_table[] = { + { + .id = WINBOND_ID_W25X16, + .l2_page_size = 8, + .pages_per_sector = 16, + .sectors_per_block = 16, + .nr_blocks = 32, + .name = "W25X16", + }, + { + .id = WINBOND_ID_W25X32, + .l2_page_size = 8, + .pages_per_sector = 16, + .sectors_per_block = 16, + .nr_blocks = 64, + .name = "W25X32", + }, + { + .id = WINBOND_ID_W25X64, + .l2_page_size = 8, + .pages_per_sector = 16, + .sectors_per_block = 16, + .nr_blocks = 128, + .name = "W25X64", + }, +}; + +static int winbond_wait_ready(struct spi_flash *flash, unsigned long timeout) +{ + struct spi_slave *spi = flash->spi; + unsigned long timebase; + int ret; + u8 status; + u8 cmd[4] = { CMD_W25_RDSR, 0xff, 0xff, 0xff }; + + ret = spi_xfer(spi, 32, &cmd[0], NULL, SPI_XFER_BEGIN); + if (ret) { + debug("SF: Failed to send command %02x: %d\n", cmd, ret); + return ret; + } + + timebase = get_timer(0); + do { + ret = spi_xfer(spi, 8, NULL, &status, 0); + if (ret) { + debug("SF: Failed to get status for cmd %02x: %d\n", cmd, ret); + return -1; + } + + if ((status & WINBOND_SR_WIP) == 0) + break; + + } while (get_timer(timebase) < timeout); + + spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); + + if ((status & WINBOND_SR_WIP) == 0) + return 0; + + debug("SF: Timed out on command %02x: %d\n", cmd, ret); + /* Timed out */ + return -1; +} + +/* + * Assemble the address part of a command for Winbond devices in + * non-power-of-two page size mode. + */ +static void winbond_build_address(struct winbond_spi_flash *stm, u8 *cmd, u32 offset) +{ + unsigned long page_addr; + unsigned long byte_addr; + unsigned long page_size; + unsigned int page_shift; + + /* + * The "extra" space per page is the power-of-two page size + * divided by 32. + */ + page_shift = stm->params->l2_page_size; + page_size = (1 << page_shift); + page_addr = offset / page_size; + byte_addr = offset % page_size; + + cmd[0] = page_addr >> (16 - page_shift); + cmd[1] = page_addr << (page_shift - 8) | (byte_addr >> 8); + cmd[2] = byte_addr; +} + +static int winbond_read_fast(struct spi_flash *flash, + u32 offset, size_t len, void *buf) +{ + struct winbond_spi_flash *stm = to_winbond_spi_flash(flash); + u8 cmd[5]; + + cmd[0] = CMD_READ_ARRAY_FAST; + winbond_build_address(stm, cmd + 1, offset); + cmd[4] = 0x00; + + return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len); +} + +static int winbond_write(struct spi_flash *flash, + u32 offset, size_t len, const void *buf) +{ + struct winbond_spi_flash *stm = to_winbond_spi_flash(flash); + unsigned long page_addr; + unsigned long byte_addr; + unsigned long page_size; + unsigned int page_shift; + size_t chunk_len; + size_t actual; + int ret; + u8 cmd[4]; + + page_shift = stm->params->l2_page_size; + page_size = (1 << page_shift); + page_addr = offset / page_size; + byte_addr = offset % page_size; + + ret = spi_claim_bus(flash->spi); + if (ret) { + debug("SF: Unable to claim SPI bus\n"); + return ret; + } + + for (actual = 0; actual < len; actual += chunk_len) { + chunk_len = min(len - actual, page_size - byte_addr); + + cmd[0] = CMD_W25_PP; + cmd[1] = page_addr >> (16 - page_shift); + cmd[2] = page_addr << (page_shift - 8) | (byte_addr >> 8); + cmd[3] = byte_addr; + debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %d\n", + buf + actual, + cmd[0], cmd[1], cmd[2], cmd[3], chunk_len); + + ret = spi_flash_cmd(flash->spi, CMD_W25_WREN, NULL, 0); + if (ret < 0) { + debug("SF: Enabling Write failed\n"); + goto out; + } + + ret = spi_flash_cmd_write(flash->spi, cmd, 4, + buf + actual, chunk_len); + if (ret < 0) { + debug("SF: Winbond Page Program failed\n"); + goto out; + } + + ret = winbond_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); + if (ret < 0) { + debug("SF: Winbond page programming timed out\n"); + goto out; + } + + page_addr++; + byte_addr = 0; + } + + debug("SF: Winbond: Successfully programmed %u bytes @ 0x%x\n", + len, offset); + ret = 0; + +out: + spi_release_bus(flash->spi); + return ret; +} + +int winbond_erase(struct spi_flash *flash, u32 offset, size_t len) +{ + struct winbond_spi_flash *stm = to_winbond_spi_flash(flash); + unsigned long sector_size; + unsigned int page_shift; + size_t actual; + int ret; + u8 cmd[4]; + + /* + * This function currently uses sector erase only. + * probably speed things up by using bulk erase + * when possible. + */ + + page_shift = stm->params->l2_page_size; + sector_size = (1 << page_shift) * stm->params->pages_per_sector; + + if (offset % sector_size || len % sector_size) { + debug("SF: Erase offset/length not multiple of sector size\n"); + return -1; + } + + len /= sector_size; + cmd[0] = CMD_W25_SE; + + ret = spi_claim_bus(flash->spi); + if (ret) { + debug("SF: Unable to claim SPI bus\n"); + return ret; + } + + for (actual = 0; actual < len; actual++) { + winbond_build_address(stm, &cmd[1], offset + actual * sector_size); + printf("Erase: %02x %02x %02x %02x\n", + cmd[0], cmd[1], cmd[2], cmd[3]); + + ret = spi_flash_cmd(flash->spi, CMD_W25_WREN, NULL, 0); + if (ret < 0) { + debug("SF: Enabling Write failed\n"); + goto out; + } + + ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0); + if (ret < 0) { + debug("SF: Winbond sector erase failed\n"); + goto out; + } + + ret = winbond_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT); + if (ret < 0) { + debug("SF: Winbond sector erase timed out\n"); + goto out; + } + } + + debug("SF: Winbond: Successfully erased %u bytes @ 0x%x\n", + len * sector_size, offset); + ret = 0; + +out: + spi_release_bus(flash->spi); + return ret; +} + +struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode) +{ + const struct winbond_spi_flash_params *params; + unsigned long page_size; + struct winbond_spi_flash *stm; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(winbond_spi_flash_table); i++) { + params = &winbond_spi_flash_table[i]; + if (params->id == ((idcode[1] << 8) | idcode[2])) + break; + } + + if (i == ARRAY_SIZE(winbond_spi_flash_table)) { + debug("SF: Unsupported Winbond ID %02x%02x\n", + idcode[1], idcode[2]); + return NULL; + } + + stm = malloc(sizeof(struct winbond_spi_flash)); + if (!stm) { + debug("SF: Failed to allocate memory\n"); + return NULL; + } + + stm->params = params; + stm->flash.spi = spi; + stm->flash.name = params->name; + + /* Assuming power-of-two page size initially. */ + page_size = 1 << params->l2_page_size; + + stm->flash.write = winbond_write; + stm->flash.erase = winbond_erase; + stm->flash.read = winbond_read_fast; + stm->flash.size = page_size * params->pages_per_sector + * params->sectors_per_block + * params->nr_blocks; + + debug("SF: Detected %s with page size %u, total %u bytes\n", + params->name, page_size, stm->flash.size); + + return &stm->flash; +} -- cgit v1.2.3 From fcffb680e77fcb48598d4a9944dbe2d4503170e0 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 14 Oct 2009 19:28:03 -0400 Subject: sf: fix stmicro offset setup while erasing Reported-by: Peter Gombos Signed-off-by: Mike Frysinger --- drivers/mtd/spi/stmicro.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c index 9b910c13f..ae0d0471f 100644 --- a/drivers/mtd/spi/stmicro.c +++ b/drivers/mtd/spi/stmicro.c @@ -281,7 +281,8 @@ int stmicro_erase(struct spi_flash *flash, u32 offset, size_t len) ret = 0; for (actual = 0; actual < len; actual++) { - cmd[1] = (offset / sector_size) + actual; + cmd[1] = offset >> 16; + offset += sector_size; ret = spi_flash_cmd(flash->spi, CMD_M25PXX_WREN, NULL, 0); if (ret < 0) { -- cgit v1.2.3