diff options
Diffstat (limited to 'drivers')
184 files changed, 11657 insertions, 2217 deletions
diff --git a/drivers/bios_emulator/atibios.c b/drivers/bios_emulator/atibios.c index dbb5e8c..3b2ed6e 100644 --- a/drivers/bios_emulator/atibios.c +++ b/drivers/bios_emulator/atibios.c @@ -52,10 +52,6 @@ /* Length of the BIOS image */ #define MAX_BIOSLEN (128 * 1024L) -/* Define some useful types and macros */ -#define true 1 -#define false 0 - /* Place to save PCI BAR's that we change and later restore */ static u32 saveROMBaseAddress; static u32 saveBaseAddress10; @@ -242,7 +238,7 @@ pcidev - PCI device info for the video card on the bus to boot VGAInfo - BIOS emulator VGA info structure RETURNS: -True if successfully initialised, false if not. +true if successfully initialised, false if not. REMARKS: Loads and POST's the display controllers BIOS, directly from the BIOS @@ -295,7 +291,7 @@ static int PCI_postController(pci_dev_t pcidev, BE_VGAInfo * VGAInfo) PARAMETERS: pcidev - PCI device info for the video card on the bus to boot pVGAInfo - Place to return VGA info structure is requested -cleanUp - True to clean up on exit, false to leave emulator active +cleanUp - true to clean up on exit, false to leave emulator active REMARKS: Boots the PCI/AGP video card on the bus using the Video ROM BIOS image diff --git a/drivers/bios_emulator/besys.c b/drivers/bios_emulator/besys.c index 84724b7..ad88a53 100644 --- a/drivers/bios_emulator/besys.c +++ b/drivers/bios_emulator/besys.c @@ -47,6 +47,8 @@ * ****************************************************************************/ +#define __io +#include <asm/io.h> #include <common.h> #include "biosemui.h" diff --git a/drivers/bios_emulator/bios.c b/drivers/bios_emulator/bios.c index 7cf4879..bcc192f 100644 --- a/drivers/bios_emulator/bios.c +++ b/drivers/bios_emulator/bios.c @@ -41,6 +41,8 @@ * ****************************************************************************/ +#define __io +#include <asm/io.h> #include <common.h> #include "biosemui.h" diff --git a/drivers/bios_emulator/include/biosemu.h b/drivers/bios_emulator/include/biosemu.h index 13cb317..e92e96e 100644 --- a/drivers/bios_emulator/include/biosemu.h +++ b/drivers/bios_emulator/include/biosemu.h @@ -127,9 +127,9 @@ biosmem_limit - Limit of the BIOS image busmem_base - Base of the VGA bus memory timer - Timer used to emulate PC timer ports timer0 - Latched value for timer 0 -timer0Latched - True if timer 0 value was just latched +timer0Latched - true if timer 0 value was just latched timer2 - Current value for timer 2 -emulateVGA - True to emulate VGA I/O and memory accesses +emulateVGA - true to emulate VGA I/O and memory accesses ****************************************************************************/ typedef struct { diff --git a/drivers/bios_emulator/x86emu/debug.c b/drivers/bios_emulator/x86emu/debug.c index 6417d09..2fa8050 100644 --- a/drivers/bios_emulator/x86emu/debug.c +++ b/drivers/bios_emulator/x86emu/debug.c @@ -309,7 +309,7 @@ void x86emu_single_step(void) case 'P': noDecode = (noDecode) ? 0 : 1; printk("Toggled decoding to %s\n", - (noDecode) ? "FALSE" : "TRUE"); + (noDecode) ? "false" : "true"); break; case 't': case 0: diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c index 8c785ae..cab7f8c 100644 --- a/drivers/block/ahci.c +++ b/drivers/block/ahci.c @@ -865,14 +865,14 @@ int scsi_exec(ccb *pccb) break; default: printf("Unsupport SCSI command 0x%02x\n", pccb->cmd[0]); - return FALSE; + return false; } if (ret) { debug("SCSI command 0x%02x ret errno %d\n", pccb->cmd[0], ret); - return FALSE; + return false; } - return TRUE; + return true; } diff --git a/drivers/block/mvsata_ide.c b/drivers/block/mvsata_ide.c index a88d0f7..42c177f 100644 --- a/drivers/block/mvsata_ide.c +++ b/drivers/block/mvsata_ide.c @@ -56,8 +56,8 @@ struct mvsata_port_registers { * Sanity checks: * - to compile at all, we need CONFIG_SYS_ATA_BASE_ADDR. * - for ide_preinit to make sense, we need at least one of - * CONFIG_SYS_ATA_IDE0_OFFSET or CONFIG_SYS_ATA_IDE0_OFFSET; - * - for inde_preinit to be called, we need CONFIG_IDE_PREINIT. + * CONFIG_SYS_ATA_IDE0_OFFSET or CONFIG_SYS_ATA_IDE1_OFFSET; + * - for ide_preinit to be called, we need CONFIG_IDE_PREINIT. * Fail with an explanation message if these conditions are not met. * This is particularly important for CONFIG_IDE_PREINIT, because * its lack would not cause a build error. diff --git a/drivers/block/sata_dwc.c b/drivers/block/sata_dwc.c index 28d87f5..49288a7 100644 --- a/drivers/block/sata_dwc.c +++ b/drivers/block/sata_dwc.c @@ -360,7 +360,7 @@ int init_sata(int dev) if (status == 0x7f) { printf("Hard Disk not found.\n"); dev_state = SATA_NODEVICE; - rc = FALSE; + rc = false; return rc; } @@ -381,7 +381,7 @@ int init_sata(int dev) printf("** TimeOUT **\n"); dev_state = SATA_NODEVICE; - rc = FALSE; + rc = false; return rc; } if ((i >= 100) && ((i % 100) == 0)) @@ -458,7 +458,7 @@ static int sata_dwc_softreset(struct ata_port *ap) } else { printf("No device found\n"); dev_state = SATA_NODEVICE; - return FALSE; + return false; } tmp = ATA_DEVICE_OBS; @@ -737,7 +737,7 @@ static int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, status = ata_busy_wait(ap, ATA_BUSY, 30000); if (status & ATA_BUSY) { printf("BSY = 0 check. timeout.\n"); - rc = FALSE; + rc = false; return rc; } @@ -987,7 +987,7 @@ unsigned ata_exec_internal(struct ata_device *dev, status = ata_busy_wait(ap, ATA_BUSY, 300000); if (status & ATA_BUSY) { printf("BSY = 0 check. timeout.\n"); - rc = FALSE; + rc = false; return rc; } @@ -997,7 +997,7 @@ unsigned ata_exec_internal(struct ata_device *dev, tag = ATA_TAG_INTERNAL; if (test_and_set_bit(tag, &ap->qc_allocated)) { - rc = FALSE; + rc = false; return rc; } @@ -1656,14 +1656,14 @@ static int check_sata_dev_state(void) ret = ata_dev_read_sectors(pdata, datalen, 0, 1); - if (ret == TRUE) + if (ret == true) break; i++; if (i > (ATA_RESET_TIME * 100)) { printf("** TimeOUT **\n"); dev_state = SATA_NODEVICE; - return FALSE; + return false; } if ((i >= 100) && ((i % 100) == 0)) @@ -1672,7 +1672,7 @@ static int check_sata_dev_state(void) dev_state = SATA_READY; - return TRUE; + return true; } static unsigned int ata_dev_set_feature(struct ata_device *dev, @@ -1772,7 +1772,7 @@ ulong sata_read(int device, ulong blknr, lbaint_t blkcnt, void *buffer) blks = 0; } - if (ata_dev_read_sectors(pdata, datalen, block, n_block) != TRUE) { + if (ata_dev_read_sectors(pdata, datalen, block, n_block) != true) { printf("sata_dwc : Hard disk read error.\n"); blkcnt -= blks; break; @@ -1795,7 +1795,7 @@ static int ata_dev_read_sectors(unsigned char *pdata, unsigned long datalen, int may_fallback = 1; if (dev_state == SATA_ERROR) - return FALSE; + return false; ata_dev_select(ap, dev->devno, 1, 1); @@ -1893,11 +1893,11 @@ retry: goto err_out; } - return TRUE; + return true; err_out: printf("failed to READ SECTORS (%s, err_mask=0x%x)\n", reason, err_mask); - return FALSE; + return false; } #if defined(CONFIG_SATA_DWC) && !defined(CONFIG_LBA48) @@ -1946,7 +1946,7 @@ ulong sata_write(int device, ulong blknr, lbaint_t blkcnt, const void *buffer) blks = 0; } - if (ata_dev_write_sectors(pdata, datalen, block, n_block) != TRUE) { + if (ata_dev_write_sectors(pdata, datalen, block, n_block) != true) { printf("sata_dwc : Hard disk read error.\n"); blkcnt -= blks; break; @@ -1969,7 +1969,7 @@ static int ata_dev_write_sectors(unsigned char* pdata, unsigned long datalen, int may_fallback = 1; if (dev_state == SATA_ERROR) - return FALSE; + return false; ata_dev_select(ap, dev->devno, 1, 1); @@ -2068,9 +2068,9 @@ retry: goto err_out; } - return TRUE; + return true; err_out: printf("failed to WRITE SECTORS (%s, err_mask=0x%x)\n", reason, err_mask); - return FALSE; + return false; } diff --git a/drivers/block/sata_dwc.h b/drivers/block/sata_dwc.h index 204d644..e4e4ab1 100644 --- a/drivers/block/sata_dwc.h +++ b/drivers/block/sata_dwc.h @@ -467,11 +467,4 @@ struct ata_port { unsigned char *pdata; }; -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - #endif diff --git a/drivers/block/sym53c8xx.c b/drivers/block/sym53c8xx.c index 564aa98..656683a 100644 --- a/drivers/block/sym53c8xx.c +++ b/drivers/block/sym53c8xx.c @@ -764,9 +764,9 @@ int scsi_exec(ccb *pccb) retry: scsi_issue(pccb); if(pccb->contr_stat!=SIR_COMPLETE) - return FALSE; + return false; if(pccb->status==S_GOOD) - return TRUE; + return true; if(pccb->status==S_CHECK_COND) { /* check condition */ for(i=0;i<16;i++) tmpcmd[i]=pccb->cmd[i]; @@ -797,12 +797,12 @@ retry: case SENSE_NO_SENSE: case SENSE_RECOVERED_ERROR: /* seems to be ok */ - return TRUE; + return true; break; case SENSE_NOT_READY: if((pccb->sense_buf[12]!=0x04)||(pccb->sense_buf[13]!=0x01)) { /* if device is not in process of becoming ready */ - return FALSE; + return false; break; } /* else fall through */ case SENSE_UNIT_ATTENTION: @@ -814,13 +814,13 @@ retry: goto retry; } PRINTF("Target %d not ready, %d retried\n",pccb->target,retrycnt); - return FALSE; + return false; default: - return FALSE; + return false; } } PRINTF("Status = %X\n",pccb->status); - return FALSE; + return false; } diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile new file mode 100644 index 0000000..2c54793 --- /dev/null +++ b/drivers/crypto/Makefile @@ -0,0 +1,47 @@ +# +# Copyright (c) 2013 Samsung Electronics Co., Ltd. +# http://www.samsung.com +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB := $(obj)libcrypto.o + +COBJS-$(CONFIG_EXYNOS_ACE_SHA) += ace_sha.o + +COBJS := $(COBJS-y) +SRCS := $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) + +all: $(LIB) + +$(LIB): $(obj).depend $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################## diff --git a/drivers/crypto/ace_sha.c b/drivers/crypto/ace_sha.c new file mode 100644 index 0000000..53ebb33 --- /dev/null +++ b/drivers/crypto/ace_sha.c @@ -0,0 +1,126 @@ +/* + * Advanced Crypto Engine - SHA Firmware + * Copyright (c) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include <common.h> +#include <sha256.h> +#include <sha1.h> +#include <asm/errno.h> +#include "ace_sha.h" + +/* SHA1 value for the message of zero length */ +static const unsigned char sha1_digest_emptymsg[SHA1_SUM_LEN] = { + 0xDA, 0x39, 0xA3, 0xEE, 0x5E, 0x6B, 0x4B, 0x0D, + 0x32, 0x55, 0xBF, 0xFF, 0x95, 0x60, 0x18, 0x90, + 0xAF, 0xD8, 0x07, 0x09}; + +/* SHA256 value for the message of zero length */ +static const unsigned char sha256_digest_emptymsg[SHA256_SUM_LEN] = { + 0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, + 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24, + 0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, + 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55}; + +int ace_sha_hash_digest(const unsigned char *pbuf, unsigned int buf_len, + unsigned char *pout, unsigned int hash_type) +{ + unsigned int i, reg, len; + unsigned int *pdigest; + struct exynos_ace_sfr *ace_sha_reg = + (struct exynos_ace_sfr *)samsung_get_base_ace_sfr(); + + if (buf_len == 0) { + /* ACE H/W cannot compute hash value for empty string */ + if (hash_type == ACE_SHA_TYPE_SHA1) + memcpy(pout, sha1_digest_emptymsg, SHA1_SUM_LEN); + else + memcpy(pout, sha256_digest_emptymsg, SHA256_SUM_LEN); + return 0; + } + + /* Flush HRDMA */ + writel(ACE_FC_HRDMACFLUSH_ON, &ace_sha_reg->fc_hrdmac); + writel(ACE_FC_HRDMACFLUSH_OFF, &ace_sha_reg->fc_hrdmac); + + /* Set byte swap of data in */ + writel(ACE_HASH_SWAPDI_ON | ACE_HASH_SWAPDO_ON | ACE_HASH_SWAPIV_ON, + &ace_sha_reg->hash_byteswap); + + /* Select Hash input mux as external source */ + reg = readl(&ace_sha_reg->fc_fifoctrl); + reg = (reg & ~ACE_FC_SELHASH_MASK) | ACE_FC_SELHASH_EXOUT; + writel(reg, &ace_sha_reg->fc_fifoctrl); + + /* Set Hash as SHA1 or SHA256 and start Hash engine */ + reg = (hash_type == ACE_SHA_TYPE_SHA1) ? + ACE_HASH_ENGSEL_SHA1HASH : ACE_HASH_ENGSEL_SHA256HASH; + reg |= ACE_HASH_STARTBIT_ON; + writel(reg, &ace_sha_reg->hash_control); + + /* Enable FIFO mode */ + writel(ACE_HASH_FIFO_ON, &ace_sha_reg->hash_fifo_mode); + + /* Set message length */ + writel(buf_len, &ace_sha_reg->hash_msgsize_low); + writel(0, &ace_sha_reg->hash_msgsize_high); + + /* Set HRDMA */ + writel((unsigned int)pbuf, &ace_sha_reg->fc_hrdmas); + writel(buf_len, &ace_sha_reg->fc_hrdmal); + + while ((readl(&ace_sha_reg->hash_status) & ACE_HASH_MSGDONE_MASK) == + ACE_HASH_MSGDONE_OFF) { + /* + * PRNG error bit goes HIGH if a PRNG request occurs without + * a complete seed setup. We are using this bit to check h/w + * fault because proper setup is not expected in that case. + */ + if ((readl(&ace_sha_reg->hash_status) + & ACE_HASH_PRNGERROR_MASK) == ACE_HASH_PRNGERROR_ON) + return -EBUSY; + } + + /* Clear MSG_DONE bit */ + writel(ACE_HASH_MSGDONE_ON, &ace_sha_reg->hash_status); + + /* Read hash result */ + pdigest = (unsigned int *)pout; + len = (hash_type == ACE_SHA_TYPE_SHA1) ? SHA1_SUM_LEN : SHA256_SUM_LEN; + + for (i = 0; i < len / 4; i++) + pdigest[i] = readl(&ace_sha_reg->hash_result[i]); + + /* Clear HRDMA pending bit */ + writel(ACE_FC_HRDMA, &ace_sha_reg->fc_intpend); + + return 0; +} + +void hw_sha256(const unsigned char *pbuf, unsigned int buf_len, + unsigned char *pout, unsigned int chunk_size) +{ + if (ace_sha_hash_digest(pbuf, buf_len, pout, ACE_SHA_TYPE_SHA256)) + debug("ACE was not setup properly or it is faulty\n"); +} + +void hw_sha1(const unsigned char *pbuf, unsigned int buf_len, + unsigned char *pout, unsigned int chunk_size) +{ + if (ace_sha_hash_digest(pbuf, buf_len, pout, ACE_SHA_TYPE_SHA1)) + debug("ACE was not setup properly or it is faulty\n"); +} diff --git a/drivers/crypto/ace_sha.h b/drivers/crypto/ace_sha.h new file mode 100644 index 0000000..0292a08 --- /dev/null +++ b/drivers/crypto/ace_sha.h @@ -0,0 +1,325 @@ +/* + * Header file for Advanced Crypto Engine - SFR definitions + * + * Copyright (c) 2012 Samsung Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __ACE_SHA_H +#define __ACE_SHA_H + +struct exynos_ace_sfr { + unsigned int fc_intstat; /* base + 0 */ + unsigned int fc_intenset; + unsigned int fc_intenclr; + unsigned int fc_intpend; + unsigned int fc_fifostat; + unsigned int fc_fifoctrl; + unsigned int fc_global; + unsigned int res1; + unsigned int fc_brdmas; + unsigned int fc_brdmal; + unsigned int fc_brdmac; + unsigned int res2; + unsigned int fc_btdmas; + unsigned int fc_btdmal; + unsigned int fc_btdmac; + unsigned int res3; + unsigned int fc_hrdmas; + unsigned int fc_hrdmal; + unsigned int fc_hrdmac; + unsigned int res4; + unsigned int fc_pkdmas; + unsigned int fc_pkdmal; + unsigned int fc_pkdmac; + unsigned int fc_pkdmao; + unsigned char res5[0x1a0]; + + unsigned int aes_control; /* base + 0x200 */ + unsigned int aes_status; + unsigned char res6[0x8]; + unsigned int aes_in[4]; + unsigned int aes_out[4]; + unsigned int aes_iv[4]; + unsigned int aes_cnt[4]; + unsigned char res7[0x30]; + unsigned int aes_key[8]; + unsigned char res8[0x60]; + + unsigned int tdes_control; /* base + 0x300 */ + unsigned int tdes_status; + unsigned char res9[0x8]; + unsigned int tdes_key[6]; + unsigned int tdes_iv[2]; + unsigned int tdes_in[2]; + unsigned int tdes_out[2]; + unsigned char res10[0xc0]; + + unsigned int hash_control; /* base + 0x400 */ + unsigned int hash_control2; + unsigned int hash_fifo_mode; + unsigned int hash_byteswap; + unsigned int hash_status; + unsigned char res11[0xc]; + unsigned int hash_msgsize_low; + unsigned int hash_msgsize_high; + unsigned int hash_prelen_low; + unsigned int hash_prelen_high; + unsigned int hash_in[16]; + unsigned int hash_key_in[16]; + unsigned int hash_iv[8]; + unsigned char res12[0x30]; + unsigned int hash_result[8]; + unsigned char res13[0x20]; + unsigned int hash_seed[8]; + unsigned int hash_prng[8]; + unsigned char res14[0x180]; + + unsigned int pka_sfr[5]; /* base + 0x700 */ +}; + +/* ACE_FC_INT */ +#define ACE_FC_PKDMA (1 << 0) +#define ACE_FC_HRDMA (1 << 1) +#define ACE_FC_BTDMA (1 << 2) +#define ACE_FC_BRDMA (1 << 3) +#define ACE_FC_PRNG_ERROR (1 << 4) +#define ACE_FC_MSG_DONE (1 << 5) +#define ACE_FC_PRNG_DONE (1 << 6) +#define ACE_FC_PARTIAL_DONE (1 << 7) + +/* ACE_FC_FIFOSTAT */ +#define ACE_FC_PKFIFO_EMPTY (1 << 0) +#define ACE_FC_PKFIFO_FULL (1 << 1) +#define ACE_FC_HRFIFO_EMPTY (1 << 2) +#define ACE_FC_HRFIFO_FULL (1 << 3) +#define ACE_FC_BTFIFO_EMPTY (1 << 4) +#define ACE_FC_BTFIFO_FULL (1 << 5) +#define ACE_FC_BRFIFO_EMPTY (1 << 6) +#define ACE_FC_BRFIFO_FULL (1 << 7) + +/* ACE_FC_FIFOCTRL */ +#define ACE_FC_SELHASH_MASK (3 << 0) +#define ACE_FC_SELHASH_EXOUT (0 << 0) /* independent source */ +#define ACE_FC_SELHASH_BCIN (1 << 0) /* blk cipher input */ +#define ACE_FC_SELHASH_BCOUT (2 << 0) /* blk cipher output */ +#define ACE_FC_SELBC_MASK (1 << 2) +#define ACE_FC_SELBC_AES (0 << 2) +#define ACE_FC_SELBC_DES (1 << 2) + +/* ACE_FC_GLOBAL */ +#define ACE_FC_SSS_RESET (1 << 0) +#define ACE_FC_DMA_RESET (1 << 1) +#define ACE_FC_AES_RESET (1 << 2) +#define ACE_FC_DES_RESET (1 << 3) +#define ACE_FC_HASH_RESET (1 << 4) +#define ACE_FC_AXI_ENDIAN_MASK (3 << 6) +#define ACE_FC_AXI_ENDIAN_LE (0 << 6) +#define ACE_FC_AXI_ENDIAN_BIBE (1 << 6) +#define ACE_FC_AXI_ENDIAN_WIBE (2 << 6) + +/* Feed control - BRDMA control */ +#define ACE_FC_BRDMACFLUSH_OFF (0 << 0) +#define ACE_FC_BRDMACFLUSH_ON (1 << 0) +#define ACE_FC_BRDMACSWAP_ON (1 << 1) +#define ACE_FC_BRDMACARPROT_MASK (0x7 << 2) +#define ACE_FC_BRDMACARPROT_OFS 2 +#define ACE_FC_BRDMACARCACHE_MASK (0xf << 5) +#define ACE_FC_BRDMACARCACHE_OFS 5 + +/* Feed control - BTDMA control */ +#define ACE_FC_BTDMACFLUSH_OFF (0 << 0) +#define ACE_FC_BTDMACFLUSH_ON (1 << 0) +#define ACE_FC_BTDMACSWAP_ON (1 << 1) +#define ACE_FC_BTDMACAWPROT_MASK (0x7 << 2) +#define ACE_FC_BTDMACAWPROT_OFS 2 +#define ACE_FC_BTDMACAWCACHE_MASK (0xf << 5) +#define ACE_FC_BTDMACAWCACHE_OFS 5 + +/* Feed control - HRDMA control */ +#define ACE_FC_HRDMACFLUSH_OFF (0 << 0) +#define ACE_FC_HRDMACFLUSH_ON (1 << 0) +#define ACE_FC_HRDMACSWAP_ON (1 << 1) +#define ACE_FC_HRDMACARPROT_MASK (0x7 << 2) +#define ACE_FC_HRDMACARPROT_OFS 2 +#define ACE_FC_HRDMACARCACHE_MASK (0xf << 5) +#define ACE_FC_HRDMACARCACHE_OFS 5 + +/* Feed control - PKDMA control */ +#define ACE_FC_PKDMACBYTESWAP_ON (1 << 3) +#define ACE_FC_PKDMACDESEND_ON (1 << 2) +#define ACE_FC_PKDMACTRANSMIT_ON (1 << 1) +#define ACE_FC_PKDMACFLUSH_ON (1 << 0) + +/* Feed control - PKDMA offset */ +#define ACE_FC_SRAMOFFSET_MASK 0xfff + +/* AES control */ +#define ACE_AES_MODE_MASK (1 << 0) +#define ACE_AES_MODE_ENC (0 << 0) +#define ACE_AES_MODE_DEC (1 << 0) +#define ACE_AES_OPERMODE_MASK (3 << 1) +#define ACE_AES_OPERMODE_ECB (0 << 1) +#define ACE_AES_OPERMODE_CBC (1 << 1) +#define ACE_AES_OPERMODE_CTR (2 << 1) +#define ACE_AES_FIFO_MASK (1 << 3) +#define ACE_AES_FIFO_OFF (0 << 3) /* CPU mode */ +#define ACE_AES_FIFO_ON (1 << 3) /* FIFO mode */ +#define ACE_AES_KEYSIZE_MASK (3 << 4) +#define ACE_AES_KEYSIZE_128 (0 << 4) +#define ACE_AES_KEYSIZE_192 (1 << 4) +#define ACE_AES_KEYSIZE_256 (2 << 4) +#define ACE_AES_KEYCNGMODE_MASK (1 << 6) +#define ACE_AES_KEYCNGMODE_OFF (0 << 6) +#define ACE_AES_KEYCNGMODE_ON (1 << 6) +#define ACE_AES_SWAP_MASK (0x1f << 7) +#define ACE_AES_SWAPKEY_OFF (0 << 7) +#define ACE_AES_SWAPKEY_ON (1 << 7) +#define ACE_AES_SWAPCNT_OFF (0 << 8) +#define ACE_AES_SWAPCNT_ON (1 << 8) +#define ACE_AES_SWAPIV_OFF (0 << 9) +#define ACE_AES_SWAPIV_ON (1 << 9) +#define ACE_AES_SWAPDO_OFF (0 << 10) +#define ACE_AES_SWAPDO_ON (1 << 10) +#define ACE_AES_SWAPDI_OFF (0 << 11) +#define ACE_AES_SWAPDI_ON (1 << 11) +#define ACE_AES_COUNTERSIZE_MASK (3 << 12) +#define ACE_AES_COUNTERSIZE_128 (0 << 12) +#define ACE_AES_COUNTERSIZE_64 (1 << 12) +#define ACE_AES_COUNTERSIZE_32 (2 << 12) +#define ACE_AES_COUNTERSIZE_16 (3 << 12) + +/* AES status */ +#define ACE_AES_OUTRDY_MASK (1 << 0) +#define ACE_AES_OUTRDY_OFF (0 << 0) +#define ACE_AES_OUTRDY_ON (1 << 0) +#define ACE_AES_INRDY_MASK (1 << 1) +#define ACE_AES_INRDY_OFF (0 << 1) +#define ACE_AES_INRDY_ON (1 << 1) +#define ACE_AES_BUSY_MASK (1 << 2) +#define ACE_AES_BUSY_OFF (0 << 2) +#define ACE_AES_BUSY_ON (1 << 2) + +/* TDES control */ +#define ACE_TDES_MODE_MASK (1 << 0) +#define ACE_TDES_MODE_ENC (0 << 0) +#define ACE_TDES_MODE_DEC (1 << 0) +#define ACE_TDES_OPERMODE_MASK (1 << 1) +#define ACE_TDES_OPERMODE_ECB (0 << 1) +#define ACE_TDES_OPERMODE_CBC (1 << 1) +#define ACE_TDES_SEL_MASK (3 << 3) +#define ACE_TDES_SEL_DES (0 << 3) +#define ACE_TDES_SEL_TDESEDE (1 << 3) /* TDES EDE mode */ +#define ACE_TDES_SEL_TDESEEE (3 << 3) /* TDES EEE mode */ +#define ACE_TDES_FIFO_MASK (1 << 5) +#define ACE_TDES_FIFO_OFF (0 << 5) /* CPU mode */ +#define ACE_TDES_FIFO_ON (1 << 5) /* FIFO mode */ +#define ACE_TDES_SWAP_MASK (0xf << 6) +#define ACE_TDES_SWAPKEY_OFF (0 << 6) +#define ACE_TDES_SWAPKEY_ON (1 << 6) +#define ACE_TDES_SWAPIV_OFF (0 << 7) +#define ACE_TDES_SWAPIV_ON (1 << 7) +#define ACE_TDES_SWAPDO_OFF (0 << 8) +#define ACE_TDES_SWAPDO_ON (1 << 8) +#define ACE_TDES_SWAPDI_OFF (0 << 9) +#define ACE_TDES_SWAPDI_ON (1 << 9) + +/* TDES status */ +#define ACE_TDES_OUTRDY_MASK (1 << 0) +#define ACE_TDES_OUTRDY_OFF (0 << 0) +#define ACE_TDES_OUTRDY_ON (1 << 0) +#define ACE_TDES_INRDY_MASK (1 << 1) +#define ACE_TDES_INRDY_OFF (0 << 1) +#define ACE_TDES_INRDY_ON (1 << 1) +#define ACE_TDES_BUSY_MASK (1 << 2) +#define ACE_TDES_BUSY_OFF (0 << 2) +#define ACE_TDES_BUSY_ON (1 << 2) + +/* Hash control */ +#define ACE_HASH_ENGSEL_MASK (0xf << 0) +#define ACE_HASH_ENGSEL_SHA1HASH (0x0 << 0) +#define ACE_HASH_ENGSEL_SHA1HMAC (0x1 << 0) +#define ACE_HASH_ENGSEL_SHA1HMACIN (0x1 << 0) +#define ACE_HASH_ENGSEL_SHA1HMACOUT (0x9 << 0) +#define ACE_HASH_ENGSEL_MD5HASH (0x2 << 0) +#define ACE_HASH_ENGSEL_MD5HMAC (0x3 << 0) +#define ACE_HASH_ENGSEL_MD5HMACIN (0x3 << 0) +#define ACE_HASH_ENGSEL_MD5HMACOUT (0xb << 0) +#define ACE_HASH_ENGSEL_SHA256HASH (0x4 << 0) +#define ACE_HASH_ENGSEL_SHA256HMAC (0x5 << 0) +#define ACE_HASH_ENGSEL_PRNG (0x8 << 0) +#define ACE_HASH_STARTBIT_ON (1 << 4) +#define ACE_HASH_USERIV_EN (1 << 5) +#define ACE_HASH_PAUSE_ON (1 << 0) + +/* Hash control - FIFO mode */ +#define ACE_HASH_FIFO_MASK (1 << 0) +#define ACE_HASH_FIFO_OFF (0 << 0) +#define ACE_HASH_FIFO_ON (1 << 0) + +/* Hash control - byte swap */ +#define ACE_HASH_SWAP_MASK (0xf << 0) +#define ACE_HASH_SWAPKEY_OFF (0 << 0) +#define ACE_HASH_SWAPKEY_ON (1 << 0) +#define ACE_HASH_SWAPIV_OFF (0 << 1) +#define ACE_HASH_SWAPIV_ON (1 << 1) +#define ACE_HASH_SWAPDO_OFF (0 << 2) +#define ACE_HASH_SWAPDO_ON (1 << 2) +#define ACE_HASH_SWAPDI_OFF (0 << 3) +#define ACE_HASH_SWAPDI_ON (1 << 3) + +/* Hash status */ +#define ACE_HASH_BUFRDY_MASK (1 << 0) +#define ACE_HASH_BUFRDY_OFF (0 << 0) +#define ACE_HASH_BUFRDY_ON (1 << 0) +#define ACE_HASH_SEEDSETTING_MASK (1 << 1) +#define ACE_HASH_SEEDSETTING_OFF (0 << 1) +#define ACE_HASH_SEEDSETTING_ON (1 << 1) +#define ACE_HASH_PRNGBUSY_MASK (1 << 2) +#define ACE_HASH_PRNGBUSY_OFF (0 << 2) +#define ACE_HASH_PRNGBUSY_ON (1 << 2) +#define ACE_HASH_PARTIALDONE_MASK (1 << 4) +#define ACE_HASH_PARTIALDONE_OFF (0 << 4) +#define ACE_HASH_PARTIALDONE_ON (1 << 4) +#define ACE_HASH_PRNGDONE_MASK (1 << 5) +#define ACE_HASH_PRNGDONE_OFF (0 << 5) +#define ACE_HASH_PRNGDONE_ON (1 << 5) +#define ACE_HASH_MSGDONE_MASK (1 << 6) +#define ACE_HASH_MSGDONE_OFF (0 << 6) +#define ACE_HASH_MSGDONE_ON (1 << 6) +#define ACE_HASH_PRNGERROR_MASK (1 << 7) +#define ACE_HASH_PRNGERROR_OFF (0 << 7) +#define ACE_HASH_PRNGERROR_ON (1 << 7) + +#define ACE_SHA_TYPE_SHA1 1 +#define ACE_SHA_TYPE_SHA256 2 + +/** + * Computes hash value of input pbuf using ACE + * + * @param in_addr A pointer to the input buffer + * @param bufleni Byte length of input buffer + * @param out_addr A pointer to the output buffer. When complete + * 32 bytes are copied to pout[0]...pout[31]. Thus, a user + * should allocate at least 32 bytes at pOut in advance. + * @param hash_type SHA1 or SHA256 + * + * @return 0 on Success, -1 on Failure (Timeout) + */ +int ace_sha_hash_digest(const uchar * in_addr, uint buflen, + uchar * out_addr, uint hash_type); +#endif diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile index 7b717bc..153095d 100644 --- a/drivers/dfu/Makefile +++ b/drivers/dfu/Makefile @@ -27,6 +27,7 @@ LIB = $(obj)libdfu.o COBJS-$(CONFIG_DFU_FUNCTION) += dfu.o COBJS-$(CONFIG_DFU_MMC) += dfu_mmc.o +COBJS-$(CONFIG_DFU_NAND) += dfu_nand.o SRCS := $(COBJS-y:.o=.c) OBJS := $(addprefix $(obj),$(COBJS-y)) diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index e8477fb..6af6890 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -44,90 +44,232 @@ static int dfu_find_alt_num(const char *s) static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE) dfu_buf[DFU_DATA_BUF_SIZE]; +static int dfu_write_buffer_drain(struct dfu_entity *dfu) +{ + long w_size; + int ret; + + /* flush size? */ + w_size = dfu->i_buf - dfu->i_buf_start; + if (w_size == 0) + return 0; + + /* update CRC32 */ + dfu->crc = crc32(dfu->crc, dfu->i_buf_start, w_size); + + ret = dfu->write_medium(dfu, dfu->offset, dfu->i_buf_start, &w_size); + if (ret) + debug("%s: Write error!\n", __func__); + + /* point back */ + dfu->i_buf = dfu->i_buf_start; + + /* update offset */ + dfu->offset += w_size; + + puts("#"); + + return ret; +} + int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) { - static unsigned char *i_buf; - static int i_blk_seq_num; - long w_size = 0; int ret = 0; + int tret; + + debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x offset: 0x%llx bufoffset: 0x%x\n", + __func__, dfu->name, buf, size, blk_seq_num, dfu->offset, + dfu->i_buf - dfu->i_buf_start); + + if (!dfu->inited) { + /* initial state */ + dfu->crc = 0; + dfu->offset = 0; + dfu->bad_skip = 0; + dfu->i_blk_seq_num = 0; + dfu->i_buf_start = dfu_buf; + dfu->i_buf_end = dfu_buf + sizeof(dfu_buf); + dfu->i_buf = dfu->i_buf_start; + + dfu->inited = 1; + } - debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf: 0x%p\n", - __func__, dfu->name, buf, size, blk_seq_num, i_buf); + if (dfu->i_blk_seq_num != blk_seq_num) { + printf("%s: Wrong sequence number! [%d] [%d]\n", + __func__, dfu->i_blk_seq_num, blk_seq_num); + return -1; + } - if (blk_seq_num == 0) { - i_buf = dfu_buf; - i_blk_seq_num = 0; + /* DFU 1.1 standard says: + * The wBlockNum field is a block sequence number. It increments each + * time a block is transferred, wrapping to zero from 65,535. It is used + * to provide useful context to the DFU loader in the device." + * + * This means that it's a 16 bit counter that roll-overs at + * 0xffff -> 0x0000. By having a typical 4K transfer block + * we roll-over at exactly 256MB. Not very fun to debug. + * + * Handling rollover, and having an inited variable, + * makes things work. + */ + + /* handle rollover */ + dfu->i_blk_seq_num = (dfu->i_blk_seq_num + 1) & 0xffff; + + /* flush buffer if overflow */ + if ((dfu->i_buf + size) > dfu->i_buf_end) { + tret = dfu_write_buffer_drain(dfu); + if (ret == 0) + ret = tret; } - if (i_blk_seq_num++ != blk_seq_num) { - printf("%s: Wrong sequence number! [%d] [%d]\n", - __func__, i_blk_seq_num, blk_seq_num); + /* we should be in buffer now (if not then size too large) */ + if ((dfu->i_buf + size) > dfu->i_buf_end) { + printf("%s: Wrong size! [%d] [%d] - %d\n", + __func__, dfu->i_blk_seq_num, blk_seq_num, size); return -1; } - memcpy(i_buf, buf, size); - i_buf += size; + memcpy(dfu->i_buf, buf, size); + dfu->i_buf += size; + /* if end or if buffer full flush */ + if (size == 0 || (dfu->i_buf + size) > dfu->i_buf_end) { + tret = dfu_write_buffer_drain(dfu); + if (ret == 0) + ret = tret; + } + + /* end? */ if (size == 0) { - /* Integrity check (if needed) */ - debug("%s: %s %d [B] CRC32: 0x%x\n", __func__, dfu->name, - i_buf - dfu_buf, crc32(0, dfu_buf, i_buf - dfu_buf)); + /* Now try and flush to the medium if needed. */ + if (dfu->flush_medium) + ret = dfu->flush_medium(dfu); + printf("\nDFU complete CRC32: 0x%08x\n", dfu->crc); - w_size = i_buf - dfu_buf; - ret = dfu->write_medium(dfu, dfu_buf, &w_size); - if (ret) - debug("%s: Write error!\n", __func__); + /* clear everything */ + dfu->crc = 0; + dfu->offset = 0; + dfu->i_blk_seq_num = 0; + dfu->i_buf_start = dfu_buf; + dfu->i_buf_end = dfu_buf + sizeof(dfu_buf); + dfu->i_buf = dfu->i_buf_start; + + dfu->inited = 0; - i_blk_seq_num = 0; - i_buf = NULL; - return ret; } - return ret; + return ret = 0 ? size : ret; +} + +static int dfu_read_buffer_fill(struct dfu_entity *dfu, void *buf, int size) +{ + long chunk; + int ret, readn; + + readn = 0; + while (size > 0) { + /* get chunk that can be read */ + chunk = min(size, dfu->b_left); + /* consume */ + if (chunk > 0) { + memcpy(buf, dfu->i_buf, chunk); + dfu->crc = crc32(dfu->crc, buf, chunk); + dfu->i_buf += chunk; + dfu->b_left -= chunk; + size -= chunk; + buf += chunk; + readn += chunk; + } + + /* all done */ + if (size > 0) { + /* no more to read */ + if (dfu->r_left == 0) + break; + + dfu->i_buf = dfu->i_buf_start; + dfu->b_left = dfu->i_buf_end - dfu->i_buf_start; + + /* got to read, but buffer is empty */ + if (dfu->b_left > dfu->r_left) + dfu->b_left = dfu->r_left; + ret = dfu->read_medium(dfu, dfu->offset, dfu->i_buf, + &dfu->b_left); + if (ret != 0) { + debug("%s: Read error!\n", __func__); + return ret; + } + dfu->offset += dfu->b_left; + dfu->r_left -= dfu->b_left; + + puts("#"); + } + } + + return readn; } int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) { - static unsigned char *i_buf; - static int i_blk_seq_num; - static long r_size; - static u32 crc; int ret = 0; debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf: 0x%p\n", - __func__, dfu->name, buf, size, blk_seq_num, i_buf); + __func__, dfu->name, buf, size, blk_seq_num, dfu->i_buf); + + if (!dfu->inited) { + ret = dfu->read_medium(dfu, 0, buf, &dfu->r_left); + if (ret != 0) { + debug("%s: failed to get r_left\n", __func__); + return ret; + } + + debug("%s: %s %ld [B]\n", __func__, dfu->name, dfu->r_left); + + dfu->i_blk_seq_num = 0; + dfu->crc = 0; + dfu->offset = 0; + dfu->i_buf_start = dfu_buf; + dfu->i_buf_end = dfu_buf + sizeof(dfu_buf); + dfu->i_buf = dfu->i_buf_start; + dfu->b_left = 0; - if (blk_seq_num == 0) { - i_buf = dfu_buf; - ret = dfu->read_medium(dfu, i_buf, &r_size); - debug("%s: %s %ld [B]\n", __func__, dfu->name, r_size); - i_blk_seq_num = 0; - /* Integrity check (if needed) */ - crc = crc32(0, dfu_buf, r_size); + dfu->bad_skip = 0; + + dfu->inited = 1; } - if (i_blk_seq_num++ != blk_seq_num) { + if (dfu->i_blk_seq_num != blk_seq_num) { printf("%s: Wrong sequence number! [%d] [%d]\n", - __func__, i_blk_seq_num, blk_seq_num); + __func__, dfu->i_blk_seq_num, blk_seq_num); return -1; } + /* handle rollover */ + dfu->i_blk_seq_num = (dfu->i_blk_seq_num + 1) & 0xffff; - if (r_size >= size) { - memcpy(buf, i_buf, size); - i_buf += size; - r_size -= size; - return size; - } else { - memcpy(buf, i_buf, r_size); - i_buf += r_size; - debug("%s: %s CRC32: 0x%x\n", __func__, dfu->name, crc); - puts("UPLOAD ... done\nCtrl+C to exit ...\n"); + ret = dfu_read_buffer_fill(dfu, buf, size); + if (ret < 0) { + printf("%s: Failed to fill buffer\n", __func__); + return -1; + } + + if (ret < size) { + debug("%s: %s CRC32: 0x%x\n", __func__, dfu->name, dfu->crc); + puts("\nUPLOAD ... done\nCtrl+C to exit ...\n"); - i_buf = NULL; - i_blk_seq_num = 0; - crc = 0; - return r_size; + dfu->i_blk_seq_num = 0; + dfu->crc = 0; + dfu->offset = 0; + dfu->i_buf_start = dfu_buf; + dfu->i_buf_end = dfu_buf + sizeof(dfu_buf); + dfu->i_buf = dfu->i_buf_start; + dfu->b_left = 0; + + dfu->bad_skip = 0; + + dfu->inited = 0; } + return ret; } @@ -147,6 +289,9 @@ static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt, if (strcmp(interface, "mmc") == 0) { if (dfu_fill_entity_mmc(dfu, s)) return -1; + } else if (strcmp(interface, "nand") == 0) { + if (dfu_fill_entity_nand(dfu, s)) + return -1; } else { printf("%s: Device %s not (yet) supported!\n", __func__, interface); diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c index 5d504df..e2f3978 100644 --- a/drivers/dfu/dfu_mmc.c +++ b/drivers/dfu/dfu_mmc.c @@ -21,6 +21,8 @@ #include <common.h> #include <malloc.h> +#include <errno.h> +#include <div64.h> #include <dfu.h> enum dfu_mmc_op { @@ -28,32 +30,51 @@ enum dfu_mmc_op { DFU_OP_WRITE, }; +static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE) + dfu_file_buf[CONFIG_SYS_DFU_MAX_FILE_SIZE]; +static long dfu_file_buf_len; + static int mmc_block_op(enum dfu_mmc_op op, struct dfu_entity *dfu, - void *buf, long *len) + u64 offset, void *buf, long *len) { char cmd_buf[DFU_CMD_BUF_SIZE]; + u32 blk_start, blk_count; + + /* + * We must ensure that we work in lba_blk_size chunks, so ALIGN + * this value. + */ + *len = ALIGN(*len, dfu->data.mmc.lba_blk_size); + + blk_start = dfu->data.mmc.lba_start + + (u32)lldiv(offset, dfu->data.mmc.lba_blk_size); + blk_count = *len / dfu->data.mmc.lba_blk_size; + if (blk_start + blk_count > + dfu->data.mmc.lba_start + dfu->data.mmc.lba_size) { + puts("Request would exceed designated area!\n"); + return -EINVAL; + } - sprintf(cmd_buf, "mmc %s 0x%x %x %x", + sprintf(cmd_buf, "mmc %s %p %x %x", op == DFU_OP_READ ? "read" : "write", - (unsigned int) buf, - dfu->data.mmc.lba_start, - dfu->data.mmc.lba_size); - - if (op == DFU_OP_READ) - *len = dfu->data.mmc.lba_blk_size * dfu->data.mmc.lba_size; + buf, blk_start, blk_count); debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf); return run_command(cmd_buf, 0); } -static inline int mmc_block_write(struct dfu_entity *dfu, void *buf, long *len) +static int mmc_file_buffer(struct dfu_entity *dfu, void *buf, long *len) { - return mmc_block_op(DFU_OP_WRITE, dfu, buf, len); -} + if (dfu_file_buf_len + *len > CONFIG_SYS_DFU_MAX_FILE_SIZE) { + dfu_file_buf_len = 0; + return -EINVAL; + } -static inline int mmc_block_read(struct dfu_entity *dfu, void *buf, long *len) -{ - return mmc_block_op(DFU_OP_READ, dfu, buf, len); + /* Add to the current buffer. */ + memcpy(dfu_file_buf + dfu_file_buf_len, buf, *len); + dfu_file_buf_len += *len; + + return 0; } static int mmc_file_op(enum dfu_mmc_op op, struct dfu_entity *dfu, @@ -65,20 +86,23 @@ static int mmc_file_op(enum dfu_mmc_op op, struct dfu_entity *dfu, switch (dfu->layout) { case DFU_FS_FAT: - sprintf(cmd_buf, "fat%s mmc %d:%d 0x%x %s %lx", + sprintf(cmd_buf, "fat%s mmc %d:%d 0x%x %s", op == DFU_OP_READ ? "load" : "write", dfu->data.mmc.dev, dfu->data.mmc.part, - (unsigned int) buf, dfu->name, *len); + (unsigned int) buf, dfu->name); + if (op == DFU_OP_WRITE) + sprintf(cmd_buf + strlen(cmd_buf), " %lx", *len); break; case DFU_FS_EXT4: - sprintf(cmd_buf, "ext4%s mmc %d:%d /%s 0x%x %ld", + sprintf(cmd_buf, "ext4%s mmc %d:%d 0x%x /%s", op == DFU_OP_READ ? "load" : "write", dfu->data.mmc.dev, dfu->data.mmc.part, - dfu->name, (unsigned int) buf, *len); + (unsigned int) buf, dfu->name); break; default: printf("%s: Layout (%s) not (yet) supported!\n", __func__, dfu_get_layout(dfu->layout)); + return -1; } debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf); @@ -101,27 +125,18 @@ static int mmc_file_op(enum dfu_mmc_op op, struct dfu_entity *dfu, return ret; } -static inline int mmc_file_write(struct dfu_entity *dfu, void *buf, long *len) -{ - return mmc_file_op(DFU_OP_WRITE, dfu, buf, len); -} - -static inline int mmc_file_read(struct dfu_entity *dfu, void *buf, long *len) -{ - return mmc_file_op(DFU_OP_READ, dfu, buf, len); -} - -int dfu_write_medium_mmc(struct dfu_entity *dfu, void *buf, long *len) +int dfu_write_medium_mmc(struct dfu_entity *dfu, + u64 offset, void *buf, long *len) { int ret = -1; switch (dfu->layout) { case DFU_RAW_ADDR: - ret = mmc_block_write(dfu, buf, len); + ret = mmc_block_op(DFU_OP_WRITE, dfu, offset, buf, len); break; case DFU_FS_FAT: case DFU_FS_EXT4: - ret = mmc_file_write(dfu, buf, len); + ret = mmc_file_buffer(dfu, buf, len); break; default: printf("%s: Layout (%s) not (yet) supported!\n", __func__, @@ -131,17 +146,34 @@ int dfu_write_medium_mmc(struct dfu_entity *dfu, void *buf, long *len) return ret; } -int dfu_read_medium_mmc(struct dfu_entity *dfu, void *buf, long *len) +int dfu_flush_medium_mmc(struct dfu_entity *dfu) +{ + int ret = 0; + + if (dfu->layout != DFU_RAW_ADDR) { + /* Do stuff here. */ + ret = mmc_file_op(DFU_OP_WRITE, dfu, &dfu_file_buf, + &dfu_file_buf_len); + + /* Now that we're done */ + dfu_file_buf_len = 0; + } + + return ret; +} + +int dfu_read_medium_mmc(struct dfu_entity *dfu, u64 offset, void *buf, + long *len) { int ret = -1; switch (dfu->layout) { case DFU_RAW_ADDR: - ret = mmc_block_read(dfu, buf, len); + ret = mmc_block_op(DFU_OP_READ, dfu, offset, buf, len); break; case DFU_FS_FAT: case DFU_FS_EXT4: - ret = mmc_file_read(dfu, buf, len); + ret = mmc_file_op(DFU_OP_READ, dfu, buf, len); break; default: printf("%s: Layout (%s) not (yet) supported!\n", __func__, @@ -153,6 +185,10 @@ int dfu_read_medium_mmc(struct dfu_entity *dfu, void *buf, long *len) int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s) { + int dev, part; + struct mmc *mmc; + block_dev_desc_t *blk_dev; + disk_partition_t partinfo; char *st; dfu->dev_type = DFU_DEV_MMC; @@ -166,8 +202,35 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s) dfu->layout = DFU_FS_FAT; } else if (!strcmp(st, "ext4")) { dfu->layout = DFU_FS_EXT4; + } else if (!strcmp(st, "part")) { + + dfu->layout = DFU_RAW_ADDR; + + dev = simple_strtoul(s, &s, 10); + s++; + part = simple_strtoul(s, &s, 10); + + mmc = find_mmc_device(dev); + if (mmc == NULL || mmc_init(mmc)) { + printf("%s: could not find mmc device #%d!\n", + __func__, dev); + return -ENODEV; + } + + blk_dev = &mmc->block_dev; + if (get_partition_info(blk_dev, part, &partinfo) != 0) { + printf("%s: could not find partition #%d on mmc device #%d!\n", + __func__, part, dev); + return -ENODEV; + } + + dfu->data.mmc.lba_start = partinfo.start; + dfu->data.mmc.lba_size = partinfo.size; + dfu->data.mmc.lba_blk_size = partinfo.blksz; + } else { printf("%s: Memory layout (%s) not supported!\n", __func__, st); + return -ENODEV; } if (dfu->layout == DFU_FS_EXT4 || dfu->layout == DFU_FS_FAT) { @@ -177,6 +240,10 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s) dfu->read_medium = dfu_read_medium_mmc; dfu->write_medium = dfu_write_medium_mmc; + dfu->flush_medium = dfu_flush_medium_mmc; + + /* initial state */ + dfu->inited = 0; return 0; } diff --git a/drivers/dfu/dfu_nand.c b/drivers/dfu/dfu_nand.c new file mode 100644 index 0000000..7dc89b2 --- /dev/null +++ b/drivers/dfu/dfu_nand.c @@ -0,0 +1,187 @@ +/* + * dfu_nand.c -- DFU for NAND routines. + * + * Copyright (C) 2012-2013 Texas Instruments, Inc. + * + * Based on dfu_mmc.c which is: + * Copyright (C) 2012 Samsung Electronics + * author: Lukasz Majewski <l.majewski@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <common.h> +#include <malloc.h> +#include <errno.h> +#include <div64.h> +#include <dfu.h> +#include <linux/mtd/mtd.h> +#include <jffs2/load_kernel.h> +#include <nand.h> + +enum dfu_nand_op { + DFU_OP_READ = 1, + DFU_OP_WRITE, +}; + +static int nand_block_op(enum dfu_nand_op op, struct dfu_entity *dfu, + u64 offset, void *buf, long *len) +{ + loff_t start, lim; + size_t count, actual; + int ret; + nand_info_t *nand; + + /* if buf == NULL return total size of the area */ + if (buf == NULL) { + *len = dfu->data.nand.size; + return 0; + } + + start = dfu->data.nand.start + offset + dfu->bad_skip; + lim = dfu->data.nand.start + dfu->data.nand.size - start; + count = *len; + + if (nand_curr_device < 0 || + nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE || + !nand_info[nand_curr_device].name) { + printf("%s: invalid nand device\n", __func__); + return -1; + } + + nand = &nand_info[nand_curr_device]; + + if (op == DFU_OP_READ) + ret = nand_read_skip_bad(nand, start, &count, &actual, + lim, buf); + else + ret = nand_write_skip_bad(nand, start, &count, &actual, + lim, buf, 0); + + if (ret != 0) { + printf("%s: nand_%s_skip_bad call failed at %llx!\n", + __func__, op == DFU_OP_READ ? "read" : "write", + start); + return ret; + } + + /* + * Find out where we stopped writing data. This can be deeper into + * the NAND than we expected due to having to skip bad blocks. So + * we must take this into account for the next write, if any. + */ + if (actual > count) + dfu->bad_skip += actual - count; + + return ret; +} + +static inline int nand_block_write(struct dfu_entity *dfu, + u64 offset, void *buf, long *len) +{ + return nand_block_op(DFU_OP_WRITE, dfu, offset, buf, len); +} + +static inline int nand_block_read(struct dfu_entity *dfu, + u64 offset, void *buf, long *len) +{ + return nand_block_op(DFU_OP_READ, dfu, offset, buf, len); +} + +static int dfu_write_medium_nand(struct dfu_entity *dfu, + u64 offset, void *buf, long *len) +{ + int ret = -1; + + switch (dfu->layout) { + case DFU_RAW_ADDR: + ret = nand_block_write(dfu, offset, buf, len); + break; + default: + printf("%s: Layout (%s) not (yet) supported!\n", __func__, + dfu_get_layout(dfu->layout)); + } + + return ret; +} + +static int dfu_read_medium_nand(struct dfu_entity *dfu, u64 offset, void *buf, + long *len) +{ + int ret = -1; + + switch (dfu->layout) { + case DFU_RAW_ADDR: + ret = nand_block_read(dfu, offset, buf, len); + break; + default: + printf("%s: Layout (%s) not (yet) supported!\n", __func__, + dfu_get_layout(dfu->layout)); + } + + return ret; +} + +int dfu_fill_entity_nand(struct dfu_entity *dfu, char *s) +{ + char *st; + int ret, dev, part; + + dfu->dev_type = DFU_DEV_NAND; + st = strsep(&s, " "); + if (!strcmp(st, "raw")) { + dfu->layout = DFU_RAW_ADDR; + dfu->data.nand.start = simple_strtoul(s, &s, 16); + s++; + dfu->data.nand.size = simple_strtoul(s, &s, 16); + } else if (!strcmp(st, "part")) { + char mtd_id[32]; + struct mtd_device *mtd_dev; + u8 part_num; + struct part_info *pi; + + dfu->layout = DFU_RAW_ADDR; + + dev = simple_strtoul(s, &s, 10); + s++; + part = simple_strtoul(s, &s, 10); + + sprintf(mtd_id, "%s%d,%d", "nand", dev, part - 1); + printf("using id '%s'\n", mtd_id); + + mtdparts_init(); + + ret = find_dev_and_part(mtd_id, &mtd_dev, &part_num, &pi); + if (ret != 0) { + printf("Could not locate '%s'\n", mtd_id); + return -1; + } + + dfu->data.nand.start = pi->offset; + dfu->data.nand.size = pi->size; + + } else { + printf("%s: Memory layout (%s) not supported!\n", __func__, st); + return -1; + } + + dfu->read_medium = dfu_read_medium_nand; + dfu->write_medium = dfu_write_medium_nand; + + /* initial state */ + dfu->inited = 0; + + return 0; +} diff --git a/drivers/fpga/ACEX1K.c b/drivers/fpga/ACEX1K.c index 4703fc1..0ae78f9 100644 --- a/drivers/fpga/ACEX1K.c +++ b/drivers/fpga/ACEX1K.c @@ -140,7 +140,7 @@ static int ACEX1K_ps_load(Altera_desc *desc, const void *buf, size_t bsize) } /* Establish the initial state */ - (*fn->config) (TRUE, TRUE, cookie); /* Assert nCONFIG */ + (*fn->config) (true, true, cookie); /* Assert nCONFIG */ udelay(2); /* T_cfg > 2us */ @@ -152,7 +152,7 @@ static int ACEX1K_ps_load(Altera_desc *desc, const void *buf, size_t bsize) return FPGA_FAIL; } - (*fn->config) (FALSE, TRUE, cookie); /* Deassert nCONFIG */ + (*fn->config) (false, true, cookie); /* Deassert nCONFIG */ udelay(2); /* T_cf2st1 < 4us */ /* Wait for nSTATUS to be released (i.e. deasserted) */ @@ -192,13 +192,13 @@ static int ACEX1K_ps_load(Altera_desc *desc, const void *buf, size_t bsize) i = 8; do { /* Deassert the clock */ - (*fn->clk) (FALSE, TRUE, cookie); + (*fn->clk) (false, true, cookie); CONFIG_FPGA_DELAY (); /* Write data */ - (*fn->data) ( (val & 0x01), TRUE, cookie); + (*fn->data) ((val & 0x01), true, cookie); CONFIG_FPGA_DELAY (); /* Assert the clock */ - (*fn->clk) (TRUE, TRUE, cookie); + (*fn->clk) (true, true, cookie); CONFIG_FPGA_DELAY (); val >>= 1; i --; @@ -232,9 +232,9 @@ static int ACEX1K_ps_load(Altera_desc *desc, const void *buf, size_t bsize) for (i = 0; i < 12; i++) { CONFIG_FPGA_DELAY (); - (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ + (*fn->clk) (true, true, cookie); /* Assert the clock pin */ CONFIG_FPGA_DELAY (); - (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ + (*fn->clk) (false, true, cookie); /* Deassert the clock pin */ } ret_val = FPGA_SUCCESS; diff --git a/drivers/fpga/altera.c b/drivers/fpga/altera.c index f087d01..8388da5 100644 --- a/drivers/fpga/altera.c +++ b/drivers/fpga/altera.c @@ -215,7 +215,7 @@ int altera_info( Altera_desc *desc ) static int altera_validate (Altera_desc * desc, const char *fn) { - int ret_val = FALSE; + int ret_val = false; if (desc) { if ((desc->family > min_altera_type) && @@ -223,7 +223,7 @@ static int altera_validate (Altera_desc * desc, const char *fn) if ((desc->iface > min_altera_iface_type) && (desc->iface < max_altera_iface_type)) { if (desc->size) { - ret_val = TRUE; + ret_val = true; } else { printf ("%s: NULL part size\n", fn); } diff --git a/drivers/fpga/cyclon2.c b/drivers/fpga/cyclon2.c index 0773e73..6b734c2 100644 --- a/drivers/fpga/cyclon2.c +++ b/drivers/fpga/cyclon2.c @@ -144,9 +144,9 @@ static int CYC2_ps_load(Altera_desc *desc, const void *buf, size_t bsize) } /* Establish the initial state */ - (*fn->config) (FALSE, TRUE, cookie); /* De-assert nCONFIG */ + (*fn->config) (false, true, cookie); /* De-assert nCONFIG */ udelay(100); - (*fn->config) (TRUE, TRUE, cookie); /* Assert nCONFIG */ + (*fn->config) (true, true, cookie); /* Assert nCONFIG */ udelay(2); /* T_cfg > 2us */ @@ -164,7 +164,7 @@ static int CYC2_ps_load(Altera_desc *desc, const void *buf, size_t bsize) /* Get ready for the burn */ CONFIG_FPGA_DELAY (); - ret = (*fn->write) (buf, bsize, TRUE, cookie); + ret = (*fn->write) (buf, bsize, true, cookie); if (ret) { puts ("** Write failed.\n"); (*fn->abort) (cookie); diff --git a/drivers/fpga/lattice.c b/drivers/fpga/lattice.c index d8b642a..8c3465a 100644 --- a/drivers/fpga/lattice.c +++ b/drivers/fpga/lattice.c @@ -275,7 +275,7 @@ signed char ispVM(void) static int lattice_validate(Lattice_desc *desc, const char *fn) { - int ret_val = FALSE; + int ret_val = false; if (desc) { if ((desc->family > min_lattice_type) && @@ -283,7 +283,7 @@ static int lattice_validate(Lattice_desc *desc, const char *fn) if ((desc->iface > min_lattice_iface_type) && (desc->iface < max_lattice_iface_type)) { if (desc->size) { - ret_val = TRUE; + ret_val = true; } else { printf("%s: NULL part size\n", fn); } diff --git a/drivers/fpga/spartan2.c b/drivers/fpga/spartan2.c index 4bc7070..0bc400d 100644 --- a/drivers/fpga/spartan2.c +++ b/drivers/fpga/spartan2.c @@ -162,11 +162,11 @@ static int Spartan2_sp_load(Xilinx_desc *desc, const void *buf, size_t bsize) } /* Establish the initial state */ - (*fn->pgm) (TRUE, TRUE, cookie); /* Assert the program, commit */ + (*fn->pgm) (true, true, cookie); /* Assert the program, commit */ /* Get ready for the burn */ CONFIG_FPGA_DELAY (); - (*fn->pgm) (FALSE, TRUE, cookie); /* Deassert the program, commit */ + (*fn->pgm) (false, true, cookie); /* Deassert the program, commit */ ts = get_timer (0); /* get current time */ /* Now wait for INIT and BUSY to go high */ @@ -179,20 +179,20 @@ static int Spartan2_sp_load(Xilinx_desc *desc, const void *buf, size_t bsize) } } while ((*fn->init) (cookie) && (*fn->busy) (cookie)); - (*fn->wr) (TRUE, TRUE, cookie); /* Assert write, commit */ - (*fn->cs) (TRUE, TRUE, cookie); /* Assert chip select, commit */ - (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ + (*fn->wr) (true, true, cookie); /* Assert write, commit */ + (*fn->cs) (true, true, cookie); /* Assert chip select, commit */ + (*fn->clk) (true, true, cookie); /* Assert the clock pin */ /* Load the data */ while (bytecount < bsize) { /* XXX - do we check for an Ctrl-C press in here ??? */ /* XXX - Check the error bit? */ - (*fn->wdata) (data[bytecount++], TRUE, cookie); /* write the data */ + (*fn->wdata) (data[bytecount++], true, cookie); /* write the data */ CONFIG_FPGA_DELAY (); - (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ + (*fn->clk) (false, true, cookie); /* Deassert the clock pin */ CONFIG_FPGA_DELAY (); - (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ + (*fn->clk) (true, true, cookie); /* Assert the clock pin */ #ifdef CONFIG_SYS_FPGA_CHECK_BUSY ts = get_timer (0); /* get current time */ @@ -201,9 +201,9 @@ static int Spartan2_sp_load(Xilinx_desc *desc, const void *buf, size_t bsize) * make sure we aren't busy forever... */ CONFIG_FPGA_DELAY (); - (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ + (*fn->clk) (false, true, cookie); /* Deassert the clock pin */ CONFIG_FPGA_DELAY (); - (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ + (*fn->clk) (true, true, cookie); /* Assert the clock pin */ if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ puts ("** Timeout waiting for BUSY to clear.\n"); @@ -220,8 +220,8 @@ static int Spartan2_sp_load(Xilinx_desc *desc, const void *buf, size_t bsize) } CONFIG_FPGA_DELAY (); - (*fn->cs) (FALSE, TRUE, cookie); /* Deassert the chip select */ - (*fn->wr) (FALSE, TRUE, cookie); /* Deassert the write pin */ + (*fn->cs) (false, true, cookie); /* Deassert the chip select */ + (*fn->wr) (false, true, cookie); /* Deassert the write pin */ #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK putc ('\n'); /* terminate the dotted line */ @@ -233,9 +233,9 @@ static int Spartan2_sp_load(Xilinx_desc *desc, const void *buf, size_t bsize) while ((*fn->done) (cookie) == FPGA_FAIL) { CONFIG_FPGA_DELAY (); - (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ + (*fn->clk) (false, true, cookie); /* Deassert the clock pin */ CONFIG_FPGA_DELAY (); - (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ + (*fn->clk) (true, true, cookie); /* Assert the clock pin */ if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ puts ("** Timeout waiting for DONE to clear.\n"); @@ -277,15 +277,15 @@ static int Spartan2_sp_dump(Xilinx_desc *desc, const void *buf, size_t bsize) printf ("Starting Dump of FPGA Device %d...\n", cookie); - (*fn->cs) (TRUE, TRUE, cookie); /* Assert chip select, commit */ - (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ + (*fn->cs) (true, true, cookie); /* Assert chip select, commit */ + (*fn->clk) (true, true, cookie); /* Assert the clock pin */ /* dump the data */ while (bytecount < bsize) { /* XXX - do we check for an Ctrl-C press in here ??? */ - (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ - (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ + (*fn->clk) (false, true, cookie); /* Deassert the clock pin */ + (*fn->clk) (true, true, cookie); /* Assert the clock pin */ (*fn->rdata) (&(data[bytecount++]), cookie); /* read the data */ #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK if (bytecount % (bsize / 40) == 0) @@ -293,9 +293,9 @@ static int Spartan2_sp_dump(Xilinx_desc *desc, const void *buf, size_t bsize) #endif } - (*fn->cs) (FALSE, FALSE, cookie); /* Deassert the chip select */ - (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ - (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ + (*fn->cs) (false, false, cookie); /* Deassert the chip select */ + (*fn->clk) (false, true, cookie); /* Deassert the clock pin */ + (*fn->clk) (true, true, cookie); /* Assert the clock pin */ #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK putc ('\n'); /* terminate the dotted line */ @@ -351,7 +351,7 @@ static int Spartan2_ss_load(Xilinx_desc *desc, const void *buf, size_t bsize) } /* Establish the initial state */ - (*fn->pgm) (TRUE, TRUE, cookie); /* Assert the program, commit */ + (*fn->pgm) (true, true, cookie); /* Assert the program, commit */ /* Wait for INIT state (init low) */ ts = get_timer (0); /* get current time */ @@ -365,7 +365,7 @@ static int Spartan2_ss_load(Xilinx_desc *desc, const void *buf, size_t bsize) /* Get ready for the burn */ CONFIG_FPGA_DELAY (); - (*fn->pgm) (FALSE, TRUE, cookie); /* Deassert the program, commit */ + (*fn->pgm) (false, true, cookie); /* Deassert the program, commit */ ts = get_timer (0); /* get current time */ /* Now wait for INIT to go high */ @@ -390,13 +390,13 @@ static int Spartan2_ss_load(Xilinx_desc *desc, const void *buf, size_t bsize) i = 8; do { /* Deassert the clock */ - (*fn->clk) (FALSE, TRUE, cookie); + (*fn->clk) (false, true, cookie); CONFIG_FPGA_DELAY (); /* Write data */ - (*fn->wr) ((val & 0x80), TRUE, cookie); + (*fn->wr) ((val & 0x80), true, cookie); CONFIG_FPGA_DELAY (); /* Assert the clock */ - (*fn->clk) (TRUE, TRUE, cookie); + (*fn->clk) (true, true, cookie); CONFIG_FPGA_DELAY (); val <<= 1; i --; @@ -417,14 +417,14 @@ static int Spartan2_ss_load(Xilinx_desc *desc, const void *buf, size_t bsize) /* now check for done signal */ ts = get_timer (0); /* get current time */ ret_val = FPGA_SUCCESS; - (*fn->wr) (TRUE, TRUE, cookie); + (*fn->wr) (true, true, cookie); while (! (*fn->done) (cookie)) { CONFIG_FPGA_DELAY (); - (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ + (*fn->clk) (false, true, cookie); /* Deassert the clock pin */ CONFIG_FPGA_DELAY (); - (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ + (*fn->clk) (true, true, cookie); /* Assert the clock pin */ putc ('*'); diff --git a/drivers/fpga/spartan3.c b/drivers/fpga/spartan3.c index 1633a70..c63c605 100644 --- a/drivers/fpga/spartan3.c +++ b/drivers/fpga/spartan3.c @@ -166,11 +166,11 @@ static int Spartan3_sp_load(Xilinx_desc *desc, const void *buf, size_t bsize) } /* Establish the initial state */ - (*fn->pgm) (TRUE, TRUE, cookie); /* Assert the program, commit */ + (*fn->pgm) (true, true, cookie); /* Assert the program, commit */ /* Get ready for the burn */ CONFIG_FPGA_DELAY (); - (*fn->pgm) (FALSE, TRUE, cookie); /* Deassert the program, commit */ + (*fn->pgm) (false, true, cookie); /* Deassert the program, commit */ ts = get_timer (0); /* get current time */ /* Now wait for INIT and BUSY to go high */ @@ -183,20 +183,20 @@ static int Spartan3_sp_load(Xilinx_desc *desc, const void *buf, size_t bsize) } } while ((*fn->init) (cookie) && (*fn->busy) (cookie)); - (*fn->wr) (TRUE, TRUE, cookie); /* Assert write, commit */ - (*fn->cs) (TRUE, TRUE, cookie); /* Assert chip select, commit */ - (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ + (*fn->wr) (true, true, cookie); /* Assert write, commit */ + (*fn->cs) (true, true, cookie); /* Assert chip select, commit */ + (*fn->clk) (true, true, cookie); /* Assert the clock pin */ /* Load the data */ while (bytecount < bsize) { /* XXX - do we check for an Ctrl-C press in here ??? */ /* XXX - Check the error bit? */ - (*fn->wdata) (data[bytecount++], TRUE, cookie); /* write the data */ + (*fn->wdata) (data[bytecount++], true, cookie); /* write the data */ CONFIG_FPGA_DELAY (); - (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ + (*fn->clk) (false, true, cookie); /* Deassert the clock pin */ CONFIG_FPGA_DELAY (); - (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ + (*fn->clk) (true, true, cookie); /* Assert the clock pin */ #ifdef CONFIG_SYS_FPGA_CHECK_BUSY ts = get_timer (0); /* get current time */ @@ -205,9 +205,9 @@ static int Spartan3_sp_load(Xilinx_desc *desc, const void *buf, size_t bsize) * make sure we aren't busy forever... */ CONFIG_FPGA_DELAY (); - (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ + (*fn->clk) (false, true, cookie); /* Deassert the clock pin */ CONFIG_FPGA_DELAY (); - (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ + (*fn->clk) (true, true, cookie); /* Assert the clock pin */ if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ puts ("** Timeout waiting for BUSY to clear.\n"); @@ -224,8 +224,8 @@ static int Spartan3_sp_load(Xilinx_desc *desc, const void *buf, size_t bsize) } CONFIG_FPGA_DELAY (); - (*fn->cs) (FALSE, TRUE, cookie); /* Deassert the chip select */ - (*fn->wr) (FALSE, TRUE, cookie); /* Deassert the write pin */ + (*fn->cs) (false, true, cookie); /* Deassert the chip select */ + (*fn->wr) (false, true, cookie); /* Deassert the write pin */ #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK putc ('\n'); /* terminate the dotted line */ @@ -239,9 +239,9 @@ static int Spartan3_sp_load(Xilinx_desc *desc, const void *buf, size_t bsize) * make sure we aren't busy forever... */ CONFIG_FPGA_DELAY (); - (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ + (*fn->clk) (false, true, cookie); /* Deassert the clock pin */ CONFIG_FPGA_DELAY (); - (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ + (*fn->clk) (true, true, cookie); /* Assert the clock pin */ if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */ puts ("** Timeout waiting for DONE to clear.\n"); @@ -283,15 +283,15 @@ static int Spartan3_sp_dump(Xilinx_desc *desc, const void *buf, size_t bsize) printf ("Starting Dump of FPGA Device %d...\n", cookie); - (*fn->cs) (TRUE, TRUE, cookie); /* Assert chip select, commit */ - (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ + (*fn->cs) (true, true, cookie); /* Assert chip select, commit */ + (*fn->clk) (true, true, cookie); /* Assert the clock pin */ /* dump the data */ while (bytecount < bsize) { /* XXX - do we check for an Ctrl-C press in here ??? */ - (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ - (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ + (*fn->clk) (false, true, cookie); /* Deassert the clock pin */ + (*fn->clk) (true, true, cookie); /* Assert the clock pin */ (*fn->rdata) (&(data[bytecount++]), cookie); /* read the data */ #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK if (bytecount % (bsize / 40) == 0) @@ -299,9 +299,9 @@ static int Spartan3_sp_dump(Xilinx_desc *desc, const void *buf, size_t bsize) #endif } - (*fn->cs) (FALSE, FALSE, cookie); /* Deassert the chip select */ - (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ - (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ + (*fn->cs) (false, false, cookie); /* Deassert the chip select */ + (*fn->clk) (false, true, cookie); /* Deassert the clock pin */ + (*fn->clk) (true, true, cookie); /* Assert the clock pin */ #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK putc ('\n'); /* terminate the dotted line */ @@ -357,7 +357,7 @@ static int Spartan3_ss_load(Xilinx_desc *desc, const void *buf, size_t bsize) } /* Establish the initial state */ - (*fn->pgm) (TRUE, TRUE, cookie); /* Assert the program, commit */ + (*fn->pgm) (true, true, cookie); /* Assert the program, commit */ /* Wait for INIT state (init low) */ ts = get_timer (0); /* get current time */ @@ -373,7 +373,7 @@ static int Spartan3_ss_load(Xilinx_desc *desc, const void *buf, size_t bsize) /* Get ready for the burn */ CONFIG_FPGA_DELAY (); - (*fn->pgm) (FALSE, TRUE, cookie); /* Deassert the program, commit */ + (*fn->pgm) (false, true, cookie); /* Deassert the program, commit */ ts = get_timer (0); /* get current time */ /* Now wait for INIT to go high */ @@ -389,7 +389,7 @@ static int Spartan3_ss_load(Xilinx_desc *desc, const void *buf, size_t bsize) /* Load the data */ if(*fn->bwr) - (*fn->bwr) (data, bsize, TRUE, cookie); + (*fn->bwr) (data, bsize, true, cookie); else { while (bytecount < bsize) { @@ -405,13 +405,13 @@ static int Spartan3_ss_load(Xilinx_desc *desc, const void *buf, size_t bsize) i = 8; do { /* Deassert the clock */ - (*fn->clk) (FALSE, TRUE, cookie); + (*fn->clk) (false, true, cookie); CONFIG_FPGA_DELAY (); /* Write data */ - (*fn->wr) ((val & 0x80), TRUE, cookie); + (*fn->wr) ((val & 0x80), true, cookie); CONFIG_FPGA_DELAY (); /* Assert the clock */ - (*fn->clk) (TRUE, TRUE, cookie); + (*fn->clk) (true, true, cookie); CONFIG_FPGA_DELAY (); val <<= 1; i --; @@ -433,16 +433,16 @@ static int Spartan3_ss_load(Xilinx_desc *desc, const void *buf, size_t bsize) /* now check for done signal */ ts = get_timer (0); /* get current time */ ret_val = FPGA_SUCCESS; - (*fn->wr) (TRUE, TRUE, cookie); + (*fn->wr) (true, true, cookie); while (! (*fn->done) (cookie)) { /* XXX - we should have a check in here somewhere to * make sure we aren't busy forever... */ CONFIG_FPGA_DELAY (); - (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ + (*fn->clk) (false, true, cookie); /* Deassert the clock pin */ CONFIG_FPGA_DELAY (); - (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ + (*fn->clk) (true, true, cookie); /* Assert the clock pin */ putc ('*'); diff --git a/drivers/fpga/virtex2.c b/drivers/fpga/virtex2.c index b26d231..3974e47 100644 --- a/drivers/fpga/virtex2.c +++ b/drivers/fpga/virtex2.c @@ -221,7 +221,7 @@ static int Virtex2_ssm_load(Xilinx_desc *desc, const void *buf, size_t bsize) * There is no maximum value for the pulse width. Check to make * sure that INIT_B goes low after assertion of PROG_B */ - (*fn->pgm) (TRUE, TRUE, cookie); + (*fn->pgm) (true, true, cookie); udelay (10); ts = get_timer (0); do { @@ -234,9 +234,9 @@ static int Virtex2_ssm_load(Xilinx_desc *desc, const void *buf, size_t bsize) } } while (!(*fn->init) (cookie)); - (*fn->pgm) (FALSE, TRUE, cookie); + (*fn->pgm) (false, true, cookie); CONFIG_FPGA_DELAY (); - (*fn->clk) (TRUE, TRUE, cookie); + (*fn->clk) (true, true, cookie); /* * Start a timer and wait for INIT_B to go high @@ -253,8 +253,8 @@ static int Virtex2_ssm_load(Xilinx_desc *desc, const void *buf, size_t bsize) } } while ((*fn->init) (cookie) && (*fn->busy) (cookie)); - (*fn->wr) (TRUE, TRUE, cookie); - (*fn->cs) (TRUE, TRUE, cookie); + (*fn->wr) (true, true, cookie); + (*fn->cs) (true, true, cookie); udelay (10000); @@ -286,15 +286,15 @@ static int Virtex2_ssm_load(Xilinx_desc *desc, const void *buf, size_t bsize) } #endif - (*fn->wdata) (data[bytecount++], TRUE, cookie); + (*fn->wdata) (data[bytecount++], true, cookie); CONFIG_FPGA_DELAY (); /* * Cycle the clock pin */ - (*fn->clk) (FALSE, TRUE, cookie); + (*fn->clk) (false, true, cookie); CONFIG_FPGA_DELAY (); - (*fn->clk) (TRUE, TRUE, cookie); + (*fn->clk) (true, true, cookie); #ifdef CONFIG_SYS_FPGA_CHECK_BUSY ts = get_timer (0); @@ -319,8 +319,8 @@ static int Virtex2_ssm_load(Xilinx_desc *desc, const void *buf, size_t bsize) * Finished writing the data; deassert FPGA CS_B and WRITE_B signals. */ CONFIG_FPGA_DELAY (); - (*fn->cs) (FALSE, TRUE, cookie); - (*fn->wr) (FALSE, TRUE, cookie); + (*fn->cs) (false, true, cookie); + (*fn->wr) (false, true, cookie); #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK putc ('\n'); @@ -381,8 +381,8 @@ static int Virtex2_ssm_dump(Xilinx_desc *desc, const void *buf, size_t bsize) printf ("Starting Dump of FPGA Device %d...\n", cookie); - (*fn->cs) (TRUE, TRUE, cookie); - (*fn->clk) (TRUE, TRUE, cookie); + (*fn->cs) (true, true, cookie); + (*fn->clk) (true, true, cookie); while (bytecount < bsize) { #ifdef CONFIG_SYS_FPGA_CHECK_CTRLC @@ -394,8 +394,8 @@ static int Virtex2_ssm_dump(Xilinx_desc *desc, const void *buf, size_t bsize) /* * Cycle the clock and read the data */ - (*fn->clk) (FALSE, TRUE, cookie); - (*fn->clk) (TRUE, TRUE, cookie); + (*fn->clk) (false, true, cookie); + (*fn->clk) (true, true, cookie); (*fn->rdata) (&(data[bytecount++]), cookie); #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK if (bytecount % (bsize / 40) == 0) @@ -406,9 +406,9 @@ static int Virtex2_ssm_dump(Xilinx_desc *desc, const void *buf, size_t bsize) /* * Deassert CS_B and cycle the clock to deselect the device. */ - (*fn->cs) (FALSE, FALSE, cookie); - (*fn->clk) (FALSE, TRUE, cookie); - (*fn->clk) (TRUE, TRUE, cookie); + (*fn->cs) (false, false, cookie); + (*fn->clk) (false, true, cookie); + (*fn->clk) (true, true, cookie); #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK putc ('\n'); diff --git a/drivers/fpga/xilinx.c b/drivers/fpga/xilinx.c index 4072cb4..32787b2 100644 --- a/drivers/fpga/xilinx.c +++ b/drivers/fpga/xilinx.c @@ -242,7 +242,7 @@ int xilinx_info (Xilinx_desc * desc) static int xilinx_validate (Xilinx_desc * desc, char *fn) { - int ret_val = FALSE; + int ret_val = false; if (desc) { if ((desc->family > min_xilinx_type) && @@ -250,7 +250,7 @@ static int xilinx_validate (Xilinx_desc * desc, char *fn) if ((desc->iface > min_xilinx_iface_type) && (desc->iface < max_xilinx_iface_type)) { if (desc->size) { - ret_val = TRUE; + ret_val = true; } else printf ("%s: NULL part size\n", fn); } else diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c index 769a2ba..46d2506 100644 --- a/drivers/i2c/s3c24x0_i2c.c +++ b/drivers/i2c/s3c24x0_i2c.c @@ -86,13 +86,6 @@ static int GetI2CSDA(void) #endif } -#if 0 -static void SetI2CSDA(int x) -{ - rGPEDAT = (rGPEDAT & ~0x8000) | (x & 1) << 15; -} -#endif - static void SetI2CSCL(int x) { struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio(); @@ -331,7 +324,7 @@ static int i2c_transfer(struct s3c24x0_i2c *i2c, writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP, &i2c->iicstat); i = 0; - while ((i < data_len) && (result = I2C_OK)) { + while ((i < data_len) && (result == I2C_OK)) { result = WaitForXfer(i2c); writel(data[i], &i2c->iicds); ReadWriteByte(i2c); @@ -343,17 +336,16 @@ static int i2c_transfer(struct s3c24x0_i2c *i2c, result = WaitForXfer(i2c); /* send STOP */ - writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat); + writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat); ReadWriteByte(i2c); break; case I2C_READ: if (addr && addr_len) { - writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat); writel(chip, &i2c->iicds); /* send START */ - writel(readl(&i2c->iicstat) | I2C_START_STOP, - &i2c->iicstat); + writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP, + &i2c->iicstat); result = WaitForXfer(i2c); if (IsACK(i2c)) { i = 0; @@ -387,11 +379,10 @@ static int i2c_transfer(struct s3c24x0_i2c *i2c, } } else { - writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat); writel(chip, &i2c->iicds); /* send START */ - writel(readl(&i2c->iicstat) | I2C_START_STOP, - &i2c->iicstat); + writel(I2C_MODE_MR | I2C_TXRX_ENA | I2C_START_STOP, + &i2c->iicstat); result = WaitForXfer(i2c); if (IsACK(i2c)) { diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 65791aa..1d6faa2 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -43,6 +43,7 @@ COBJS-$(CONFIG_MXS_MMC) += mxsmmc.o COBJS-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o COBJS-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o COBJS-$(CONFIG_SDHCI) += sdhci.o +COBJS-$(CONFIG_BCM2835_SDHCI) += bcm2835_sdhci.o COBJS-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o COBJS-$(CONFIG_SH_MMCIF) += sh_mmcif.o COBJS-$(CONFIG_TEGRA_MMC) += tegra_mmc.o diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c new file mode 100644 index 0000000..54cfabf --- /dev/null +++ b/drivers/mmc/bcm2835_sdhci.c @@ -0,0 +1,190 @@ +/* + * This code was extracted from: + * git://github.com/gonzoua/u-boot-pi.git master + * and hence presumably (C) 2012 Oleksandr Tymoshenko + * + * Tweaks for U-Boot upstreaming + * (C) 2012 Stephen Warren + * + * Portions (e.g. read/write macros, concepts for back-to-back register write + * timing workarounds) obviously extracted from the Linux kernel at: + * https://github.com/raspberrypi/linux.git rpi-3.6.y + * + * The Linux kernel code has the following (c) and license, which is hence + * propagated to Oleksandr's tree and here: + * + * Support for SDHCI device on 2835 + * Based on sdhci-bcm2708.c (c) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Supports: + * SDHCI platform device - Arasan SD controller in BCM2708 + * + * Inspired by sdhci-pci.c, by Pierre Ossman + */ + +#include <common.h> +#include <malloc.h> +#include <sdhci.h> +#include <asm/arch/timer.h> + +/* 400KHz is max freq for card ID etc. Use that as min */ +#define MIN_FREQ 400000 + +struct bcm2835_sdhci_host { + struct sdhci_host host; + uint twoticks_delay; + ulong last_write; +}; + +static inline struct bcm2835_sdhci_host *to_bcm(struct sdhci_host *host) +{ + return (struct bcm2835_sdhci_host *)host; +} + +static inline void bcm2835_sdhci_raw_writel(struct sdhci_host *host, u32 val, + int reg) +{ + struct bcm2835_sdhci_host *bcm_host = to_bcm(host); + + /* + * The Arasan has a bugette whereby it may lose the content of + * successive writes to registers that are within two SD-card clock + * cycles of each other (a clock domain crossing problem). + * It seems, however, that the data register does not have this problem. + * (Which is just as well - otherwise we'd have to nobble the DMA engine + * too) + */ + while (get_timer_us(bcm_host->last_write) < bcm_host->twoticks_delay) + ; + + writel(val, host->ioaddr + reg); + bcm_host->last_write = get_timer_us(0); +} + +static inline u32 bcm2835_sdhci_raw_readl(struct sdhci_host *host, int reg) +{ + return readl(host->ioaddr + reg); +} + +static void bcm2835_sdhci_writel(struct sdhci_host *host, u32 val, int reg) +{ + bcm2835_sdhci_raw_writel(host, val, reg); +} + +static void bcm2835_sdhci_writew(struct sdhci_host *host, u16 val, int reg) +{ + static u32 shadow; + u32 oldval = (reg == SDHCI_COMMAND) ? shadow : + bcm2835_sdhci_raw_readl(host, reg & ~3); + u32 word_num = (reg >> 1) & 1; + u32 word_shift = word_num * 16; + u32 mask = 0xffff << word_shift; + u32 newval = (oldval & ~mask) | (val << word_shift); + + if (reg == SDHCI_TRANSFER_MODE) + shadow = newval; + else + bcm2835_sdhci_raw_writel(host, newval, reg & ~3); +} + +static void bcm2835_sdhci_writeb(struct sdhci_host *host, u8 val, int reg) +{ + u32 oldval = bcm2835_sdhci_raw_readl(host, reg & ~3); + u32 byte_num = reg & 3; + u32 byte_shift = byte_num * 8; + u32 mask = 0xff << byte_shift; + u32 newval = (oldval & ~mask) | (val << byte_shift); + + bcm2835_sdhci_raw_writel(host, newval, reg & ~3); +} + +static u32 bcm2835_sdhci_readl(struct sdhci_host *host, int reg) +{ + u32 val = bcm2835_sdhci_raw_readl(host, reg); + + return val; +} + +static u16 bcm2835_sdhci_readw(struct sdhci_host *host, int reg) +{ + u32 val = bcm2835_sdhci_raw_readl(host, (reg & ~3)); + u32 word_num = (reg >> 1) & 1; + u32 word_shift = word_num * 16; + u32 word = (val >> word_shift) & 0xffff; + + return word; +} + +static u8 bcm2835_sdhci_readb(struct sdhci_host *host, int reg) +{ + u32 val = bcm2835_sdhci_raw_readl(host, (reg & ~3)); + u32 byte_num = reg & 3; + u32 byte_shift = byte_num * 8; + u32 byte = (val >> byte_shift) & 0xff; + + return byte; +} + +static const struct sdhci_ops bcm2835_ops = { + .write_l = bcm2835_sdhci_writel, + .write_w = bcm2835_sdhci_writew, + .write_b = bcm2835_sdhci_writeb, + .read_l = bcm2835_sdhci_readl, + .read_w = bcm2835_sdhci_readw, + .read_b = bcm2835_sdhci_readb, +}; + +int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq) +{ + struct bcm2835_sdhci_host *bcm_host; + struct sdhci_host *host; + + bcm_host = malloc(sizeof(*bcm_host)); + if (!bcm_host) { + printf("sdhci_host malloc fail!\n"); + return 1; + } + + /* + * See the comments in bcm2835_sdhci_raw_writel(). + * + * This should probably be dynamically calculated based on the actual + * frequency. However, this is the longest we'll have to wait, and + * doesn't seem to slow access down too much, so the added complexity + * doesn't seem worth it for now. + * + * 1/MIN_FREQ is (max) time per tick of eMMC clock. + * 2/MIN_FREQ is time for two ticks. + * Multiply by 1000000 to get uS per two ticks. + * +1 for hack rounding. + */ + bcm_host->twoticks_delay = ((2 * 1000000) / MIN_FREQ) + 1; + bcm_host->last_write = 0; + + host = &bcm_host->host; + host->name = "bcm2835_sdhci"; + host->ioaddr = (void *)regbase; + host->quirks = SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_BROKEN_R1B | + SDHCI_QUIRK_WAIT_SEND_CMD; + host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; + host->ops = &bcm2835_ops; + + host->version = sdhci_readw(host, SDHCI_HOST_VERSION); + add_sdhci(host, emmc_freq, MIN_FREQ); + + return 0; +} diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 7b5fdd9..d732581 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -51,8 +51,12 @@ int mmc_getwp(struct mmc *mmc) wp = board_mmc_getwp(mmc); - if ((wp < 0) && mmc->getwp) - wp = mmc->getwp(mmc); + if (wp < 0) { + if (mmc->getwp) + wp = mmc->getwp(mmc); + else + wp = 0; + } return wp; } @@ -692,8 +696,12 @@ int mmc_getcd(struct mmc *mmc) cd = board_mmc_getcd(mmc); - if ((cd < 0) && mmc->getcd) - cd = mmc->getcd(mmc); + if (cd < 0) { + if (mmc->getcd) + cd = mmc->getcd(mmc); + else + cd = 1; + } return cd; } diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index 67cfcc2..166744c 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -593,8 +593,6 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio, mmc->send_cmd = mmc_send_cmd; mmc->set_ios = mmc_set_ios; mmc->init = mmc_init_setup; - mmc->getcd = omap_mmc_getcd; - mmc->getwp = omap_mmc_getwp; mmc->priv = priv_data; switch (dev_index) { @@ -616,7 +614,13 @@ int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio, return 1; } priv_data->cd_gpio = omap_mmc_setup_gpio_in(cd_gpio, "mmc_cd"); + if (priv_data->cd_gpio != -1) + mmc->getcd = omap_mmc_getcd; + priv_data->wp_gpio = omap_mmc_setup_gpio_in(wp_gpio, "mmc_wp"); + if (priv_data->wp_gpio != -1) + mmc->getwp = omap_mmc_getwp; + mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; mmc->host_caps = (MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC) & ~host_caps_mask; diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index daca0ea..1eaea04 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -412,9 +412,11 @@ int sdhci_init(struct mmc *mmc) status = sdhci_readl(host, SDHCI_PRESENT_STATE); } - /* Eable all state */ - sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_ENABLE); - sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_SIGNAL_ENABLE); + /* Enable only interrupts served by the SD controller */ + sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK + , SDHCI_INT_ENABLE); + /* Mask all sdhci interrupt sources */ + sdhci_writel(host, 0x0, SDHCI_SIGNAL_ENABLE); return 0; } diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c index 60dbb78..cf10b0d 100644 --- a/drivers/mtd/cfi_flash.c +++ b/drivers/mtd/cfi_flash.c @@ -210,9 +210,11 @@ unsigned long flash_sector_size(flash_info_t *info, flash_sect_t sect) static inline void * flash_map (flash_info_t * info, flash_sect_t sect, uint offset) { - unsigned int byte_offset = offset * info->portwidth; + unsigned int byte_offset = offset * info->portwidth / info->chipwidth; + unsigned int addr = (info->start[sect] + byte_offset); + unsigned int mask = 0xffffffff << (info->portwidth - 1); - return (void *)(info->start[sect] + byte_offset); + return (void *)(uintptr_t)(addr & mask); } static inline void flash_unmap(flash_info_t *info, flash_sect_t sect, @@ -398,6 +400,8 @@ void flash_write_cmd (flash_info_t * info, flash_sect_t sect, #endif flash_write64(cword.ll, addr); break; + default: + printf("fwc: Unknown port width %d\n", info->portwidth); } /* Ensure all the instructions are fully finished */ @@ -585,7 +589,6 @@ static int flash_status_check (flash_info_t * info, flash_sect_t sector, prompt, info->start[sector], flash_read_long (info, sector, 0)); flash_write_cmd (info, sector, 0, info->cmd_reset); - udelay(1); return ERR_TIMOUT; } udelay (1); /* also triggers watchdog */ @@ -753,12 +756,8 @@ static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c) static flash_sect_t find_sector (flash_info_t * info, ulong addr) { static flash_sect_t saved_sector; /* previously found sector */ - static flash_info_t *saved_info; /* previously used flash bank */ flash_sect_t sector = saved_sector; - if ((info != saved_info) || (sector >= info->sector_count)) - sector = 0; - while ((info->start[sector] < addr) && (sector < info->sector_count - 1)) sector++; @@ -770,7 +769,6 @@ static flash_sect_t find_sector (flash_info_t * info, ulong addr) sector--; saved_sector = sector; - saved_info = info; return sector; } @@ -787,12 +785,15 @@ static int flash_write_cfiword (flash_info_t * info, ulong dest, /* Check if Flash is (sufficiently) erased */ switch (info->portwidth) { case FLASH_CFI_8BIT: + debug("%s: 8-bit 0x%02x\n", __func__, cword.c); flag = ((flash_read8(dstaddr) & cword.c) == cword.c); break; case FLASH_CFI_16BIT: + debug("%s: 16-bit 0x%04x\n", __func__, cword.w); flag = ((flash_read16(dstaddr) & cword.w) == cword.w); break; case FLASH_CFI_32BIT: + debug("%s: 32-bit 0x%08lx\n", __func__, cword.l); flag = ((flash_read32(dstaddr) & cword.l) == cword.l); break; case FLASH_CFI_64BIT: @@ -1053,6 +1054,8 @@ int flash_erase (flash_info_t * info, int s_first, int s_last) flash_sect_t sect; int st; + debug("%s: erasing sectors %d to %d\n", __func__, s_first, s_last); + if (info->flash_id != FLASH_MAN_CFI) { puts ("Can't erase unknown flash type - aborted\n"); return 1; @@ -1162,6 +1165,9 @@ int flash_erase (flash_info_t * info, int s_first, int s_last) rcode = 1; else if (flash_verbose) putc ('.'); + } else { + debug("\nSector %d is protected.\n", + info->protect[sect]); } } @@ -1857,7 +1863,7 @@ static void flash_read_cfi (flash_info_t *info, void *buf, unsigned int i; for (i = 0; i < len; i++) - p[i] = flash_read_uchar(info, start + i); + p[i] = flash_read_uchar(info, start + (i * 2)); } static void __flash_cmd_reset(flash_info_t *info) @@ -1878,21 +1884,40 @@ static int __flash_detect_cfi (flash_info_t * info, struct cfi_qry *qry) { int cfi_offset; - /* Issue FLASH reset command */ - flash_cmd_reset(info); - for (cfi_offset=0; cfi_offset < sizeof(flash_offset_cfi) / sizeof(uint); cfi_offset++) { + /* Issue FLASH reset command */ + flash_cmd_reset(info); flash_write_cmd (info, 0, flash_offset_cfi[cfi_offset], FLASH_CMD_CFI); - if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q') - && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R') - && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) { + if (flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP, 'Q') && + flash_isequal(info, 0, + FLASH_OFFSET_CFI_RESP + 2, 'R') && + flash_isequal(info, 0, + FLASH_OFFSET_CFI_RESP + 4, 'Y')) { flash_read_cfi(info, qry, FLASH_OFFSET_CFI_RESP, sizeof(struct cfi_qry)); +#ifdef CONFIG_SYS_FLASH_INTERFACE_WIDTH + info->interface = CONFIG_SYS_FLASH_INTERFACE_WIDTH; +#else info->interface = le16_to_cpu(qry->interface_desc); - + /* Some flash chips can support multiple bus widths. + * In this case, override the interface width and + * limit it to the port width. + */ + if ((info->interface == FLASH_CFI_X8X16) && + (info->portwidth == FLASH_CFI_8BIT)) { + debug("Overriding 16-bit interface" + " width to 8-bit port width.\n"); + info->interface = FLASH_CFI_X8; + } else if ((info->interface == FLASH_CFI_X16X32) && + (info->portwidth == FLASH_CFI_16BIT)) { + debug("Overriding 16-bit interface" + " width to 16-bit port width.\n"); + info->interface = FLASH_CFI_X16; + } +#endif info->cfi_offset = flash_offset_cfi[cfi_offset]; debug ("device interface is %d\n", info->interface); @@ -1903,8 +1928,8 @@ static int __flash_detect_cfi (flash_info_t * info, struct cfi_qry *qry) info->chipwidth << CFI_FLASH_SHIFT_WIDTH); /* calculate command offsets as in the Linux driver */ - info->addr_unlock1 = 0x555; - info->addr_unlock2 = 0x2aa; + info->addr_unlock1 = 0xaaa; + info->addr_unlock2 = 0x555; /* * modify the unlock address if we are @@ -1938,8 +1963,12 @@ static int flash_detect_cfi (flash_info_t * info, struct cfi_qry *qry) for (info->chipwidth = FLASH_CFI_BY8; info->chipwidth <= info->portwidth; info->chipwidth <<= 1) - if (__flash_detect_cfi(info, qry)) + if (__flash_detect_cfi(info, qry)) { + debug("Found CFI flash, portwidth %d," + " chipwidth %d\n", + info->portwidth, info->chipwidth); return 1; + } } debug ("not found\n"); return 0; @@ -1958,7 +1987,7 @@ static void flash_fixup_amd(flash_info_t *info, struct cfi_qry *qry) /* CFI < 1.1, try to guess from device id */ if ((info->device_id & 0x80) != 0) cfi_reverse_geometry(qry); - } else if (flash_read_uchar(info, info->ext_addr + 0xf) == 3) { + } else if (flash_read_uchar(info, info->ext_addr + 0x1e) == 3) { /* CFI >= 1.1, deduct from top/bottom flag */ /* note: ext_addr is valid since cfi_version > 0 */ cfi_reverse_geometry(qry); @@ -2024,6 +2053,26 @@ static void flash_fixup_sst(flash_info_t *info, struct cfi_qry *qry) } } +static void flash_fixup_num(flash_info_t *info, struct cfi_qry *qry) +{ + /* + * The M29EW devices seem to report the CFI information wrong + * when it's in 8 bit mode. + * There's an app note from Numonyx on this issue. + * So adjust the buffer size for M29EW while operating in 8-bit mode + */ + if (((qry->max_buf_write_size) > 0x8) && + (info->device_id == 0x7E) && + (info->device_id2 == 0x2201 || + info->device_id2 == 0x2301 || + info->device_id2 == 0x2801 || + info->device_id2 == 0x4801)) { + debug("Adjusted buffer size on Numonyx flash" + " M29EW family in 8 bit mode\n"); + qry->max_buf_write_size = 0x8; + } +} + /* * The following code cannot be run from FLASH! * @@ -2054,14 +2103,15 @@ ulong flash_get_size (phys_addr_t base, int banknum) if (flash_detect_cfi (info, &qry)) { info->vendor = le16_to_cpu(qry.p_id); - info->ext_addr = le16_to_cpu(qry.p_adr); + info->ext_addr = le16_to_cpu(qry.p_adr) * 2; + debug("extended address is 0x%x\n", info->ext_addr); num_erase_regions = qry.num_erase_regions; if (info->ext_addr) { info->cfi_version = (ushort) flash_read_uchar (info, - info->ext_addr + 3) << 8; + info->ext_addr + 6) << 8; info->cfi_version |= (ushort) flash_read_uchar (info, - info->ext_addr + 4); + info->ext_addr + 8); } #ifdef DEBUG @@ -2105,6 +2155,9 @@ ulong flash_get_size (phys_addr_t base, int banknum) case 0x00bf: /* SST */ flash_fixup_sst(info, &qry); break; + case 0x0089: /* Numonyx */ + flash_fixup_num(info, &qry); + break; } debug ("manufacturer is %d\n", info->vendor); @@ -2112,6 +2165,8 @@ ulong flash_get_size (phys_addr_t base, int banknum) debug ("device id is 0x%x\n", info->device_id); debug ("device id2 is 0x%x\n", info->device_id2); debug ("cfi version is 0x%04x\n", info->cfi_version); + debug("port width: %d, chipwidth: %d, interface: %d\n", + info->portwidth, info->chipwidth, info->interface); size_ratio = info->portwidth / info->chipwidth; /* if the chip is x8/x16 reduce the ratio by half */ diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 96dcda2..cbfc679 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -347,16 +347,18 @@ static struct mtd_part *add_one_partition(struct mtd_info *master, if (mtd_mod_by_eb(cur_offset, master) != 0) { /* Round up to next erasesize */ slave->offset = (mtd_div_by_eb(cur_offset, master) + 1) * master->erasesize; - printk(KERN_NOTICE "Moving partition %d: " - "0x%012llx -> 0x%012llx\n", partno, - (unsigned long long)cur_offset, (unsigned long long)slave->offset); + debug("Moving partition %d: 0x%012llx -> 0x%012llx\n", + partno, (unsigned long long)cur_offset, + (unsigned long long)slave->offset); } } if (slave->mtd.size == MTDPART_SIZ_FULL) slave->mtd.size = master->size - slave->offset; - printk(KERN_NOTICE "0x%012llx-0x%012llx : \"%s\"\n", (unsigned long long)slave->offset, - (unsigned long long)(slave->offset + slave->mtd.size), slave->mtd.name); + debug("0x%012llx-0x%012llx : \"%s\"\n", + (unsigned long long)slave->offset, + (unsigned long long)(slave->offset + slave->mtd.size), + slave->mtd.name); /* let's do some sanity checks */ if (slave->offset >= master->size) { @@ -463,7 +465,7 @@ int add_mtd_partitions(struct mtd_info *master, if (mtd_partitions.next == NULL) INIT_LIST_HEAD(&mtd_partitions); - printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); + debug("Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); for (i = 0; i < nbparts; i++) { slave = add_one_partition(master, parts + i, i, cur_offset); diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index c77c0c4..35769c5 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -73,7 +73,6 @@ COBJS-$(CONFIG_NAND_MXS) += mxs_nand.o COBJS-$(CONFIG_NAND_NDFC) += ndfc.o COBJS-$(CONFIG_NAND_NOMADIK) += nomadik.o COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o -COBJS-$(CONFIG_NAND_S3C64XX) += s3c64xx.o COBJS-$(CONFIG_NAND_SPEAR) += spr_nand.o COBJS-$(CONFIG_TEGRA_NAND) += tegra_nand.o COBJS-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o @@ -82,6 +81,7 @@ COBJS-$(CONFIG_NAND_PLAT) += nand_plat.o else # minimal SPL drivers COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_spl.o +COBJS-$(CONFIG_NAND_MXC) += mxc_nand_spl.o endif # drivers endif # nand diff --git a/drivers/mtd/nand/kirkwood_nand.c b/drivers/mtd/nand/kirkwood_nand.c index bdab5aa..0a99a10 100644 --- a/drivers/mtd/nand/kirkwood_nand.c +++ b/drivers/mtd/nand/kirkwood_nand.c @@ -74,7 +74,11 @@ void kw_nand_select_chip(struct mtd_info *mtd, int chip) int board_nand_init(struct nand_chip *nand) { nand->options = NAND_COPYBACK | NAND_CACHEPRG | NAND_NO_PADDING; +#if defined(CONFIG_NAND_ECC_BCH) + nand->ecc.mode = NAND_ECC_SOFT_BCH; +#else nand->ecc.mode = NAND_ECC_SOFT; +#endif nand->cmd_ctrl = kw_nand_hwcontrol; nand->chip_delay = 40; nand->select_chip = kw_nand_select_chip; diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index d0ded48..eeba521 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -22,20 +22,22 @@ #include <nand.h> #include <linux/err.h> #include <asm/io.h> -#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX35) +#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX35) || \ + defined(CONFIG_MX51) || defined(CONFIG_MX53) #include <asm/arch/imx-regs.h> #endif -#include <fsl_nfc.h> +#include "mxc_nand.h" #define DRIVER_NAME "mxc_nand" -typedef enum {false, true} bool; - struct mxc_nand_host { struct mtd_info mtd; struct nand_chip *nand; - struct fsl_nfc_regs __iomem *regs; + struct mxc_nand_regs __iomem *regs; +#ifdef MXC_NFC_V3_2 + struct mxc_nand_ip_regs __iomem *ip_regs; +#endif int spare_only; int status_request; int pagesize_2k; @@ -77,7 +79,7 @@ static struct nand_ecclayout nand_hw_eccoob2k = { .oobfree = { {2, 4}, {11, 11}, {27, 11}, {43, 11}, {59, 5} }, }; #endif -#elif defined(MXC_NFC_V2_1) +#elif defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2) #ifndef CONFIG_SYS_NAND_LARGEPAGE static struct nand_ecclayout nand_hw_eccoob = { .eccbytes = 9, @@ -98,45 +100,14 @@ static struct nand_ecclayout nand_hw_eccoob2k = { #endif #endif -#ifdef CONFIG_MX27 -static int is_16bit_nand(void) -{ - struct system_control_regs *sc_regs = - (struct system_control_regs *)IMX_SYSTEM_CTL_BASE; - - if (readl(&sc_regs->fmcr) & NF_16BIT_SEL) - return 1; - else - return 0; -} -#elif defined(CONFIG_MX31) static int is_16bit_nand(void) { - struct clock_control_regs *sc_regs = - (struct clock_control_regs *)CCM_BASE; - - if (readl(&sc_regs->rcsr) & CCM_RCSR_NF16B) - return 1; - else - return 0; -} -#elif defined(CONFIG_MX25) || defined(CONFIG_MX35) -static int is_16bit_nand(void) -{ - struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; - - if (readl(&ccm->rcsr) & CCM_RCSR_NF_16BIT_SEL) - return 1; - else - return 0; -} +#if defined(CONFIG_SYS_NAND_BUSWIDTH_16BIT) + return 1; #else -#warning "8/16 bit NAND autodetection not supported" -static int is_16bit_nand(void) -{ return 0; -} #endif +} static uint32_t *mxc_nand_memcpy32(uint32_t *dest, uint32_t *source, size_t size) { @@ -150,7 +121,7 @@ static uint32_t *mxc_nand_memcpy32(uint32_t *dest, uint32_t *source, size_t size /* * This function polls the NANDFC to wait for the basic operation to - * complete by checking the INT bit of config2 register. + * complete by checking the INT bit. */ static void wait_op_done(struct mxc_nand_host *host, int max_retries, uint16_t param) @@ -158,10 +129,17 @@ static void wait_op_done(struct mxc_nand_host *host, int max_retries, uint32_t tmp; while (max_retries-- > 0) { - if (readw(&host->regs->config2) & NFC_INT) { - tmp = readw(&host->regs->config2); - tmp &= ~NFC_INT; - writew(tmp, &host->regs->config2); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + tmp = readnfc(&host->regs->config2); + if (tmp & NFC_V1_V2_CONFIG2_INT) { + tmp &= ~NFC_V1_V2_CONFIG2_INT; + writenfc(tmp, &host->regs->config2); +#elif defined(MXC_NFC_V3_2) + tmp = readnfc(&host->ip_regs->ipc); + if (tmp & NFC_V3_IPC_INT) { + tmp &= ~NFC_V3_IPC_INT; + writenfc(tmp, &host->ip_regs->ipc); +#endif break; } udelay(1); @@ -180,8 +158,8 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd) { MTDDEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x)\n", cmd); - writew(cmd, &host->regs->flash_cmd); - writew(NFC_CMD, &host->regs->config2); + writenfc(cmd, &host->regs->flash_cmd); + writenfc(NFC_CMD, &host->regs->operation); /* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, cmd); @@ -196,8 +174,8 @@ static void send_addr(struct mxc_nand_host *host, uint16_t addr) { MTDDEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x)\n", addr); - writew(addr, &host->regs->flash_addr); - writew(NFC_ADDR, &host->regs->config2); + writenfc(addr, &host->regs->flash_addr); + writenfc(NFC_ADDR, &host->regs->operation); /* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, addr); @@ -213,7 +191,7 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id, if (spare_only) MTDDEBUG(MTD_DEBUG_LEVEL1, "send_prog_page (%d)\n", spare_only); - if (is_mxc_nfc_21()) { + if (is_mxc_nfc_21() || is_mxc_nfc_32()) { int i; /* * The controller copies the 64 bytes of spare data from @@ -229,19 +207,26 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id, } } - writew(buf_id, &host->regs->buf_addr); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + writenfc(buf_id, &host->regs->buf_addr); +#elif defined(MXC_NFC_V3_2) + uint32_t tmp = readnfc(&host->regs->config1); + tmp &= ~NFC_V3_CONFIG1_RBA_MASK; + tmp |= NFC_V3_CONFIG1_RBA(buf_id); + writenfc(tmp, &host->regs->config1); +#endif /* Configure spare or page+spare access */ if (!host->pagesize_2k) { - uint16_t config1 = readw(&host->regs->config1); + uint32_t config1 = readnfc(&host->regs->config1); if (spare_only) - config1 |= NFC_SP_EN; + config1 |= NFC_CONFIG1_SP_EN; else - config1 &= ~NFC_SP_EN; - writew(config1, &host->regs->config1); + config1 &= ~NFC_CONFIG1_SP_EN; + writenfc(config1, &host->regs->config1); } - writew(NFC_INPUT, &host->regs->config2); + writenfc(NFC_INPUT, &host->regs->operation); /* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, spare_only); @@ -256,24 +241,31 @@ static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id, { MTDDEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", spare_only); - writew(buf_id, &host->regs->buf_addr); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + writenfc(buf_id, &host->regs->buf_addr); +#elif defined(MXC_NFC_V3_2) + uint32_t tmp = readnfc(&host->regs->config1); + tmp &= ~NFC_V3_CONFIG1_RBA_MASK; + tmp |= NFC_V3_CONFIG1_RBA(buf_id); + writenfc(tmp, &host->regs->config1); +#endif /* Configure spare or page+spare access */ if (!host->pagesize_2k) { - uint32_t config1 = readw(&host->regs->config1); + uint32_t config1 = readnfc(&host->regs->config1); if (spare_only) - config1 |= NFC_SP_EN; + config1 |= NFC_CONFIG1_SP_EN; else - config1 &= ~NFC_SP_EN; - writew(config1, &host->regs->config1); + config1 &= ~NFC_CONFIG1_SP_EN; + writenfc(config1, &host->regs->config1); } - writew(NFC_OUTPUT, &host->regs->config2); + writenfc(NFC_OUTPUT, &host->regs->operation); /* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, spare_only); - if (is_mxc_nfc_21()) { + if (is_mxc_nfc_21() || is_mxc_nfc_32()) { int i; /* @@ -293,17 +285,23 @@ static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id, /* Request the NANDFC to perform a read of the NAND device ID. */ static void send_read_id(struct mxc_nand_host *host) { - uint16_t tmp; + uint32_t tmp; +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) /* NANDFC buffer 0 is used for device ID output */ - writew(0x0, &host->regs->buf_addr); + writenfc(0x0, &host->regs->buf_addr); +#elif defined(MXC_NFC_V3_2) + tmp = readnfc(&host->regs->config1); + tmp &= ~NFC_V3_CONFIG1_RBA_MASK; + writenfc(tmp, &host->regs->config1); +#endif /* Read ID into main buffer */ - tmp = readw(&host->regs->config1); - tmp &= ~NFC_SP_EN; - writew(tmp, &host->regs->config1); + tmp = readnfc(&host->regs->config1); + tmp &= ~NFC_CONFIG1_SP_EN; + writenfc(tmp, &host->regs->config1); - writew(NFC_ID, &host->regs->config2); + writenfc(NFC_ID, &host->regs->operation); /* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, 0); @@ -315,32 +313,40 @@ static void send_read_id(struct mxc_nand_host *host) */ static uint16_t get_dev_status(struct mxc_nand_host *host) { +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) void __iomem *main_buf = host->regs->main_area[1]; uint32_t store; - uint16_t ret, tmp; +#endif + uint32_t ret, tmp; /* Issue status request to NAND device */ +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) /* store the main area1 first word, later do recovery */ store = readl(main_buf); /* NANDFC buffer 1 is used for device status */ - writew(1, &host->regs->buf_addr); + writenfc(1, &host->regs->buf_addr); +#endif /* Read status into main buffer */ - tmp = readw(&host->regs->config1); - tmp &= ~NFC_SP_EN; - writew(tmp, &host->regs->config1); + tmp = readnfc(&host->regs->config1); + tmp &= ~NFC_CONFIG1_SP_EN; + writenfc(tmp, &host->regs->config1); - writew(NFC_STATUS, &host->regs->config2); + writenfc(NFC_STATUS, &host->regs->operation); /* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, 0); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) /* * Status is placed in first word of main buffer * get status, then recovery area 1 data */ ret = readw(main_buf); writel(store, main_buf); +#elif defined(MXC_NFC_V3_2) + ret = readnfc(&host->regs->config1) >> 16; +#endif return ret; } @@ -359,13 +365,23 @@ static void _mxc_nand_enable_hwecc(struct mtd_info *mtd, int on) { struct nand_chip *nand_chip = mtd->priv; struct mxc_nand_host *host = nand_chip->priv; - uint16_t tmp = readw(&host->regs->config1); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + uint16_t tmp = readnfc(&host->regs->config1); if (on) - tmp |= NFC_ECC_EN; + tmp |= NFC_V1_V2_CONFIG1_ECC_EN; else - tmp &= ~NFC_ECC_EN; - writew(tmp, &host->regs->config1); + tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN; + writenfc(tmp, &host->regs->config1); +#elif defined(MXC_NFC_V3_2) + uint32_t tmp = readnfc(&host->ip_regs->config2); + + if (on) + tmp |= NFC_V3_CONFIG2_ECC_EN; + else + tmp &= ~NFC_V3_CONFIG2_ECC_EN; + writenfc(tmp, &host->ip_regs->config2); +#endif } #ifdef CONFIG_MXC_NAND_HWECC @@ -377,7 +393,7 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) */ } -#ifdef MXC_NFC_V2_1 +#if defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2) static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, int page, int sndcmd) @@ -391,7 +407,7 @@ static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd, MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: Reading OOB area of page %u to oob %p\n", - __FUNCTION__, host->page_addr, buf); + __func__, page, buf); chip->cmdfunc(mtd, NAND_CMD_READOOB, mtd->writesize, page); for (i = 0; i < chip->ecc.steps; i++) { @@ -445,7 +461,7 @@ static int mxc_nand_read_page_raw_syndrome(struct mtd_info *mtd, int n; _mxc_nand_enable_hwecc(mtd, 0); - chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, host->page_addr); + chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); for (n = 0, steps = chip->ecc.steps; steps > 0; n++, steps--) { host->col_addr = n * eccsize; @@ -489,7 +505,7 @@ static int mxc_nand_read_page_syndrome(struct mtd_info *mtd, uint8_t *oob = chip->oob_poi; MTDDEBUG(MTD_DEBUG_LEVEL1, "Reading page %u to buf %p oob %p\n", - host->page_addr, buf, oob); + page, buf, oob); /* first read the data area and the available portion of OOB */ for (n = 0; eccsteps; n++, eccsteps--, p += eccsize) { @@ -527,7 +543,7 @@ static int mxc_nand_read_page_syndrome(struct mtd_info *mtd, /* Then switch ECC off and read the OOB area to get the ECC code */ _mxc_nand_enable_hwecc(mtd, 0); - chip->cmdfunc(mtd, NAND_CMD_READOOB, mtd->writesize, host->page_addr); + chip->cmdfunc(mtd, NAND_CMD_READOOB, mtd->writesize, page); eccsteps = chip->ecc.steps; oob = chip->oob_poi + chip->ecc.prepad; for (n = 0; eccsteps; n++, eccsteps--, p += eccsize) { @@ -698,7 +714,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, * additional correction. 2-Bit errors cannot be corrected by * HW ECC, so we need to return failure */ - uint16_t ecc_status = readw(&host->regs->ecc_status_result); + uint16_t ecc_status = readnfc(&host->regs->ecc_status_result); if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { MTDDEBUG(MTD_DEBUG_LEVEL0, @@ -1167,8 +1183,8 @@ static struct nand_bbt_descr bbt_mirror_descr = { int board_nand_init(struct nand_chip *this) { struct mtd_info *mtd; -#ifdef MXC_NFC_V2_1 - uint16_t tmp; +#if defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2) + uint32_t tmp; #endif #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT @@ -1195,14 +1211,18 @@ int board_nand_init(struct nand_chip *this) this->read_buf = mxc_nand_read_buf; this->verify_buf = mxc_nand_verify_buf; - host->regs = (struct fsl_nfc_regs __iomem *)CONFIG_MXC_NAND_REGS_BASE; + host->regs = (struct mxc_nand_regs __iomem *)CONFIG_MXC_NAND_REGS_BASE; +#ifdef MXC_NFC_V3_2 + host->ip_regs = + (struct mxc_nand_ip_regs __iomem *)CONFIG_MXC_NAND_IP_REGS_BASE; +#endif host->clk_act = 1; #ifdef CONFIG_MXC_NAND_HWECC this->ecc.calculate = mxc_nand_calculate_ecc; this->ecc.hwctl = mxc_nand_enable_hwecc; this->ecc.correct = mxc_nand_correct_data; - if (is_mxc_nfc_21()) { + if (is_mxc_nfc_21() || is_mxc_nfc_32()) { this->ecc.mode = NAND_ECC_HW_SYNDROME; this->ecc.read_page = mxc_nand_read_page_syndrome; this->ecc.read_page_raw = mxc_nand_read_page_raw_syndrome; @@ -1240,25 +1260,26 @@ int board_nand_init(struct nand_chip *this) this->ecc.layout = &nand_hw_eccoob; #endif +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) #ifdef MXC_NFC_V2_1 - tmp = readw(&host->regs->config1); - tmp |= NFC_ONE_CYCLE; - tmp |= NFC_4_8N_ECC; - writew(tmp, &host->regs->config1); + tmp = readnfc(&host->regs->config1); + tmp |= NFC_V2_CONFIG1_ONE_CYCLE; + tmp |= NFC_V2_CONFIG1_ECC_MODE_4; + writenfc(tmp, &host->regs->config1); if (host->pagesize_2k) - writew(64/2, &host->regs->spare_area_size); + writenfc(64/2, &host->regs->spare_area_size); else - writew(16/2, &host->regs->spare_area_size); + writenfc(16/2, &host->regs->spare_area_size); #endif /* * preset operation * Unlock the internal RAM Buffer */ - writew(0x2, &host->regs->config); + writenfc(0x2, &host->regs->config); /* Blocks to be unlocked */ - writew(0x0, &host->regs->unlockstart_blkaddr); + writenfc(0x0, &host->regs->unlockstart_blkaddr); /* Originally (Freescale LTIB 2.6.21) 0x4000 was written to the * unlockend_blkaddr, but the magic 0x4000 does not always work * when writing more than some 32 megabytes (on 2k page nands) @@ -1270,10 +1291,53 @@ int board_nand_init(struct nand_chip *this) * This might be NAND chip specific and the i.MX31 datasheet is * extremely vague about the semantics of this register. */ - writew(0xFFFF, &host->regs->unlockend_blkaddr); + writenfc(0xFFFF, &host->regs->unlockend_blkaddr); /* Unlock Block Command for given address range */ - writew(0x4, &host->regs->wrprot); + writenfc(0x4, &host->regs->wrprot); +#elif defined(MXC_NFC_V3_2) + writenfc(NFC_V3_CONFIG1_RBA(0), &host->regs->config1); + writenfc(NFC_V3_IPC_CREQ, &host->ip_regs->ipc); + + /* Unlock the internal RAM Buffer */ + writenfc(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK, + &host->ip_regs->wrprot); + + /* Blocks to be unlocked */ + for (tmp = 0; tmp < CONFIG_SYS_NAND_MAX_CHIPS; tmp++) + writenfc(0x0 | 0xFFFF << 16, + &host->ip_regs->wrprot_unlock_blkaddr[tmp]); + + writenfc(0, &host->ip_regs->ipc); + + tmp = readnfc(&host->ip_regs->config2); + tmp &= ~(NFC_V3_CONFIG2_SPAS_MASK | NFC_V3_CONFIG2_EDC_MASK | + NFC_V3_CONFIG2_ECC_MODE_8 | NFC_V3_CONFIG2_PS_MASK); + tmp |= NFC_V3_CONFIG2_ONE_CYCLE; + + if (host->pagesize_2k) { + tmp |= NFC_V3_CONFIG2_SPAS(64/2); + tmp |= NFC_V3_CONFIG2_PS_2048; + } else { + tmp |= NFC_V3_CONFIG2_SPAS(16/2); + tmp |= NFC_V3_CONFIG2_PS_512; + } + + writenfc(tmp, &host->ip_regs->config2); + + tmp = NFC_V3_CONFIG3_NUM_OF_DEVS(0) | + NFC_V3_CONFIG3_NO_SDMA | + NFC_V3_CONFIG3_RBB_MODE | + NFC_V3_CONFIG3_SBB(6) | /* Reset default */ + NFC_V3_CONFIG3_ADD_OP(0); + + if (!(this->options & NAND_BUSWIDTH_16)) + tmp |= NFC_V3_CONFIG3_FW8; + + writenfc(tmp, &host->ip_regs->config3); + + writenfc(0, &host->ip_regs->delay_line); +#endif return 0; } diff --git a/drivers/mtd/nand/mxc_nand.h b/drivers/mtd/nand/mxc_nand.h new file mode 100644 index 0000000..308ff8d --- /dev/null +++ b/drivers/mtd/nand/mxc_nand.h @@ -0,0 +1,225 @@ +/* + * (c) 2009 Magnus Lilja <lilja.magnus@gmail.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __MXC_NAND_H +#define __MXC_NAND_H + +/* + * Register map and bit definitions for the Freescale NAND Flash Controller + * present in various i.MX devices. + * + * MX31 and MX27 have version 1, which has: + * 4 512-byte main buffers and + * 4 16-byte spare buffers + * to support up to 2K byte pagesize nand. + * Reading or writing a 2K page requires 4 FDI/FDO cycles. + * + * MX25 and MX35 have version 2.1, and MX51 and MX53 have version 3.2, which + * have: + * 8 512-byte main buffers and + * 8 64-byte spare buffers + * to support up to 4K byte pagesize nand. + * Reading or writing a 2K or 4K page requires only 1 FDI/FDO cycle. + * Also some of registers are moved and/or changed meaning as seen below. + */ +#if defined(CONFIG_MX27) || defined(CONFIG_MX31) +#define MXC_NFC_V1 +#define is_mxc_nfc_1() 1 +#define is_mxc_nfc_21() 0 +#define is_mxc_nfc_32() 0 +#elif defined(CONFIG_MX25) || defined(CONFIG_MX35) +#define MXC_NFC_V2_1 +#define is_mxc_nfc_1() 0 +#define is_mxc_nfc_21() 1 +#define is_mxc_nfc_32() 0 +#elif defined(CONFIG_MX51) || defined(CONFIG_MX53) +#define MXC_NFC_V3 +#define MXC_NFC_V3_2 +#define is_mxc_nfc_1() 0 +#define is_mxc_nfc_21() 0 +#define is_mxc_nfc_32() 1 +#else +#error "MXC NFC implementation not supported" +#endif +#define is_mxc_nfc_3() is_mxc_nfc_32() + +#if defined(MXC_NFC_V1) +#define NAND_MXC_NR_BUFS 4 +#define NAND_MXC_SPARE_BUF_SIZE 16 +#define NAND_MXC_REG_OFFSET 0xe00 +#define NAND_MXC_2K_MULTI_CYCLE +#elif defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2) +#define NAND_MXC_NR_BUFS 8 +#define NAND_MXC_SPARE_BUF_SIZE 64 +#define NAND_MXC_REG_OFFSET 0x1e00 +#endif + +struct mxc_nand_regs { + u8 main_area[NAND_MXC_NR_BUFS][0x200]; + u8 spare_area[NAND_MXC_NR_BUFS][NAND_MXC_SPARE_BUF_SIZE]; + /* + * reserved size is offset of nfc registers + * minus total main and spare sizes + */ + u8 reserved1[NAND_MXC_REG_OFFSET + - NAND_MXC_NR_BUFS * (512 + NAND_MXC_SPARE_BUF_SIZE)]; +#if defined(MXC_NFC_V1) + u16 buf_size; + u16 reserved2; + u16 buf_addr; + u16 flash_addr; + u16 flash_cmd; + u16 config; + u16 ecc_status_result; + u16 rsltmain_area; + u16 rsltspare_area; + u16 wrprot; + u16 unlockstart_blkaddr; + u16 unlockend_blkaddr; + u16 nf_wrprst; + u16 config1; + u16 config2; +#elif defined(MXC_NFC_V2_1) + u16 reserved2[2]; + u16 buf_addr; + u16 flash_addr; + u16 flash_cmd; + u16 config; + u32 ecc_status_result; + u16 spare_area_size; + u16 wrprot; + u16 reserved3[2]; + u16 nf_wrprst; + u16 config1; + u16 config2; + u16 reserved4; + u16 unlockstart_blkaddr; + u16 unlockend_blkaddr; + u16 unlockstart_blkaddr1; + u16 unlockend_blkaddr1; + u16 unlockstart_blkaddr2; + u16 unlockend_blkaddr2; + u16 unlockstart_blkaddr3; + u16 unlockend_blkaddr3; +#elif defined(MXC_NFC_V3_2) + u32 flash_cmd; + u32 flash_addr[12]; + u32 config1; + u32 ecc_status_result; + u32 status_sum; + u32 launch; +#endif +}; + +#ifdef MXC_NFC_V3_2 +struct mxc_nand_ip_regs { + u32 wrprot; + u32 wrprot_unlock_blkaddr[8]; + u32 config2; + u32 config3; + u32 ipc; + u32 err_addr; + u32 delay_line; +}; +#endif + +/* Set FCMD to 1, rest to 0 for Command operation */ +#define NFC_CMD 0x1 + +/* Set FADD to 1, rest to 0 for Address operation */ +#define NFC_ADDR 0x2 + +/* Set FDI to 1, rest to 0 for Input operation */ +#define NFC_INPUT 0x4 + +/* Set FDO to 001, rest to 0 for Data Output operation */ +#define NFC_OUTPUT 0x8 + +/* Set FDO to 010, rest to 0 for Read ID operation */ +#define NFC_ID 0x10 + +/* Set FDO to 100, rest to 0 for Read Status operation */ +#define NFC_STATUS 0x20 + +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) +#define NFC_CONFIG1_SP_EN (1 << 2) +#define NFC_CONFIG1_RST (1 << 6) +#define NFC_CONFIG1_CE (1 << 7) +#elif defined(MXC_NFC_V3_2) +#define NFC_CONFIG1_SP_EN (1 << 0) +#define NFC_CONFIG1_CE (1 << 1) +#define NFC_CONFIG1_RST (1 << 2) +#endif +#define NFC_V1_V2_CONFIG1_ECC_EN (1 << 3) +#define NFC_V1_V2_CONFIG1_INT_MSK (1 << 4) +#define NFC_V1_V2_CONFIG1_BIG (1 << 5) +#define NFC_V2_CONFIG1_ECC_MODE_4 (1 << 0) +#define NFC_V2_CONFIG1_ONE_CYCLE (1 << 8) +#define NFC_V2_CONFIG1_FP_INT (1 << 11) +#define NFC_V3_CONFIG1_RBA_MASK (0x7 << 4) +#define NFC_V3_CONFIG1_RBA(x) (((x) & 0x7) << 4) + +#define NFC_V1_V2_CONFIG2_INT (1 << 15) +#define NFC_V3_CONFIG2_PS_MASK (0x3 << 0) +#define NFC_V3_CONFIG2_PS_512 (0 << 0) +#define NFC_V3_CONFIG2_PS_2048 (1 << 0) +#define NFC_V3_CONFIG2_PS_4096 (2 << 0) +#define NFC_V3_CONFIG2_ONE_CYCLE (1 << 2) +#define NFC_V3_CONFIG2_ECC_EN (1 << 3) +#define NFC_V3_CONFIG2_2CMD_PHASES (1 << 4) +#define NFC_V3_CONFIG2_NUM_ADDR_PH0 (1 << 5) +#define NFC_V3_CONFIG2_ECC_MODE_8 (1 << 6) +#define NFC_V3_CONFIG2_PPB_MASK (0x3 << 7) +#define NFC_V3_CONFIG2_PPB(x) (((x) & 0x3) << 7) +#define NFC_V3_CONFIG2_EDC_MASK (0x7 << 9) +#define NFC_V3_CONFIG2_EDC(x) (((x) & 0x7) << 9) +#define NFC_V3_CONFIG2_NUM_ADDR_PH1(x) (((x) & 0x3) << 12) +#define NFC_V3_CONFIG2_INT_MSK (1 << 15) +#define NFC_V3_CONFIG2_SPAS_MASK (0xff << 16) +#define NFC_V3_CONFIG2_SPAS(x) (((x) & 0xff) << 16) +#define NFC_V3_CONFIG2_ST_CMD_MASK (0xff << 24) +#define NFC_V3_CONFIG2_ST_CMD(x) (((x) & 0xff) << 24) + +#define NFC_V3_CONFIG3_ADD_OP(x) (((x) & 0x3) << 0) +#define NFC_V3_CONFIG3_FW8 (1 << 3) +#define NFC_V3_CONFIG3_SBB(x) (((x) & 0x7) << 8) +#define NFC_V3_CONFIG3_NUM_OF_DEVS(x) (((x) & 0x7) << 12) +#define NFC_V3_CONFIG3_RBB_MODE (1 << 15) +#define NFC_V3_CONFIG3_NO_SDMA (1 << 20) + +#define NFC_V3_WRPROT_UNLOCK (1 << 2) +#define NFC_V3_WRPROT_BLS_UNLOCK (2 << 6) + +#define NFC_V3_IPC_CREQ (1 << 0) +#define NFC_V3_IPC_INT (1 << 31) + +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) +#define operation config2 +#define readnfc readw +#define writenfc writew +#elif defined(MXC_NFC_V3_2) +#define operation launch +#define readnfc readl +#define writenfc writel +#endif + +#endif /* __MXC_NAND_H */ diff --git a/drivers/mtd/nand/mxc_nand_spl.c b/drivers/mtd/nand/mxc_nand_spl.c new file mode 100644 index 0000000..09f23c3 --- /dev/null +++ b/drivers/mtd/nand/mxc_nand_spl.c @@ -0,0 +1,366 @@ +/* + * (C) Copyright 2009 + * Magnus Lilja <lilja.magnus@gmail.com> + * + * (C) Copyright 2008 + * Maxim Artamonov, <scn1874 at yandex.ru> + * + * (C) Copyright 2006-2008 + * Stefan Roese, DENX Software Engineering, sr at denx.de. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <nand.h> +#include <asm/arch/imx-regs.h> +#include <asm/io.h> +#include "mxc_nand.h" + +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) +static struct mxc_nand_regs *const nfc = (void *)NFC_BASE_ADDR; +#elif defined(MXC_NFC_V3_2) +static struct mxc_nand_regs *const nfc = (void *)NFC_BASE_ADDR_AXI; +static struct mxc_nand_ip_regs *const nfc_ip = (void *)NFC_BASE_ADDR; +#endif + +static void nfc_wait_ready(void) +{ + uint32_t tmp; + +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + while (!(readnfc(&nfc->config2) & NFC_V1_V2_CONFIG2_INT)) + ; + + /* Reset interrupt flag */ + tmp = readnfc(&nfc->config2); + tmp &= ~NFC_V1_V2_CONFIG2_INT; + writenfc(tmp, &nfc->config2); +#elif defined(MXC_NFC_V3_2) + while (!(readnfc(&nfc_ip->ipc) & NFC_V3_IPC_INT)) + ; + + /* Reset interrupt flag */ + tmp = readnfc(&nfc_ip->ipc); + tmp &= ~NFC_V3_IPC_INT; + writenfc(tmp, &nfc_ip->ipc); +#endif +} + +static void nfc_nand_init(void) +{ +#if defined(MXC_NFC_V3_2) + int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; + int tmp; + + tmp = (readnfc(&nfc_ip->config2) & ~(NFC_V3_CONFIG2_SPAS_MASK | + NFC_V3_CONFIG2_EDC_MASK | NFC_V3_CONFIG2_PS_MASK)) | + NFC_V3_CONFIG2_SPAS(CONFIG_SYS_NAND_OOBSIZE / 2) | + NFC_V3_CONFIG2_INT_MSK | NFC_V3_CONFIG2_ECC_EN | + NFC_V3_CONFIG2_ONE_CYCLE; + if (CONFIG_SYS_NAND_PAGE_SIZE == 4096) + tmp |= NFC_V3_CONFIG2_PS_4096; + else if (CONFIG_SYS_NAND_PAGE_SIZE == 2048) + tmp |= NFC_V3_CONFIG2_PS_2048; + else if (CONFIG_SYS_NAND_PAGE_SIZE == 512) + tmp |= NFC_V3_CONFIG2_PS_512; + /* + * if spare size is larger that 16 bytes per 512 byte hunk + * then use 8 symbol correction instead of 4 + */ + if (CONFIG_SYS_NAND_OOBSIZE / ecc_per_page > 16) + tmp |= NFC_V3_CONFIG2_ECC_MODE_8; + else + tmp &= ~NFC_V3_CONFIG2_ECC_MODE_8; + writenfc(tmp, &nfc_ip->config2); + + tmp = NFC_V3_CONFIG3_NUM_OF_DEVS(0) | + NFC_V3_CONFIG3_NO_SDMA | + NFC_V3_CONFIG3_RBB_MODE | + NFC_V3_CONFIG3_SBB(6) | /* Reset default */ + NFC_V3_CONFIG3_ADD_OP(0); +#ifndef CONFIG_SYS_NAND_BUSWIDTH_16 + tmp |= NFC_V3_CONFIG3_FW8; +#endif + writenfc(tmp, &nfc_ip->config3); + + writenfc(0, &nfc_ip->delay_line); +#elif defined(MXC_NFC_V2_1) + int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; + int config1; + + writenfc(CONFIG_SYS_NAND_OOBSIZE / 2, &nfc->spare_area_size); + + /* unlocking RAM Buff */ + writenfc(0x2, &nfc->config); + + /* hardware ECC checking and correct */ + config1 = readnfc(&nfc->config1) | NFC_V1_V2_CONFIG1_ECC_EN | + NFC_V1_V2_CONFIG1_INT_MSK | NFC_V2_CONFIG1_ONE_CYCLE | + NFC_V2_CONFIG1_FP_INT; + /* + * if spare size is larger that 16 bytes per 512 byte hunk + * then use 8 symbol correction instead of 4 + */ + if (CONFIG_SYS_NAND_OOBSIZE / ecc_per_page > 16) + config1 &= ~NFC_V2_CONFIG1_ECC_MODE_4; + else + config1 |= NFC_V2_CONFIG1_ECC_MODE_4; + writenfc(config1, &nfc->config1); +#elif defined(MXC_NFC_V1) + /* unlocking RAM Buff */ + writenfc(0x2, &nfc->config); + + /* hardware ECC checking and correct */ + writenfc(NFC_V1_V2_CONFIG1_ECC_EN | NFC_V1_V2_CONFIG1_INT_MSK, + &nfc->config1); +#endif +} + +static void nfc_nand_command(unsigned short command) +{ + writenfc(command, &nfc->flash_cmd); + writenfc(NFC_CMD, &nfc->operation); + nfc_wait_ready(); +} + +static void nfc_nand_address(unsigned short address) +{ + writenfc(address, &nfc->flash_addr); + writenfc(NFC_ADDR, &nfc->operation); + nfc_wait_ready(); +} + +static void nfc_nand_page_address(unsigned int page_address) +{ + unsigned int page_count; + + nfc_nand_address(0x00); + + /* code only for large page flash */ + if (CONFIG_SYS_NAND_PAGE_SIZE > 512) + nfc_nand_address(0x00); + + page_count = CONFIG_SYS_NAND_SIZE / CONFIG_SYS_NAND_PAGE_SIZE; + + if (page_address <= page_count) { + page_count--; /* transform 0x01000000 to 0x00ffffff */ + do { + nfc_nand_address(page_address & 0xff); + page_address = page_address >> 8; + page_count = page_count >> 8; + } while (page_count); + } + + nfc_nand_address(0x00); +} + +static void nfc_nand_data_output(void) +{ +#ifdef NAND_MXC_2K_MULTI_CYCLE + int i; +#endif + +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + writenfc(0, &nfc->buf_addr); +#elif defined(MXC_NFC_V3_2) + int config1 = readnfc(&nfc->config1); + config1 &= ~NFC_V3_CONFIG1_RBA_MASK; + writenfc(config1, &nfc->config1); +#endif + writenfc(NFC_OUTPUT, &nfc->operation); + nfc_wait_ready(); +#ifdef NAND_MXC_2K_MULTI_CYCLE + /* + * This NAND controller requires multiple input commands + * for pages larger than 512 bytes. + */ + for (i = 1; i < CONFIG_SYS_NAND_PAGE_SIZE / 512; i++) { + writenfc(i, &nfc->buf_addr); + writenfc(NFC_OUTPUT, &nfc->operation); + nfc_wait_ready(); + } +#endif +} + +static int nfc_nand_check_ecc(void) +{ +#if defined(MXC_NFC_V1) + u16 ecc_status = readw(&nfc->ecc_status_result); + return (ecc_status & 0x3) == 2 || (ecc_status >> 2) == 2; +#elif defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2) + u32 ecc_status = readl(&nfc->ecc_status_result); + int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; + int err_limit = CONFIG_SYS_NAND_OOBSIZE / ecc_per_page > 16 ? 8 : 4; + int subpages = CONFIG_SYS_NAND_PAGE_SIZE / 512; + + do { + if ((ecc_status & 0xf) > err_limit) + return 1; + ecc_status >>= 4; + } while (--subpages); + + return 0; +#endif +} + +static void nfc_nand_read_page(unsigned int page_address) +{ + /* read in first 0 buffer */ +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + writenfc(0, &nfc->buf_addr); +#elif defined(MXC_NFC_V3_2) + int config1 = readnfc(&nfc->config1); + config1 &= ~NFC_V3_CONFIG1_RBA_MASK; + writenfc(config1, &nfc->config1); +#endif + nfc_nand_command(NAND_CMD_READ0); + nfc_nand_page_address(page_address); + + if (CONFIG_SYS_NAND_PAGE_SIZE > 512) + nfc_nand_command(NAND_CMD_READSTART); + + nfc_nand_data_output(); /* fill the main buffer 0 */ +} + +static int nfc_read_page(unsigned int page_address, unsigned char *buf) +{ + int i; + u32 *src; + u32 *dst; + + nfc_nand_read_page(page_address); + + if (nfc_nand_check_ecc()) + return -1; + + src = (u32 *)&nfc->main_area[0][0]; + dst = (u32 *)buf; + + /* main copy loop from NAND-buffer to SDRAM memory */ + for (i = 0; i < CONFIG_SYS_NAND_PAGE_SIZE / 4; i++) { + writel(readl(src), dst); + src++; + dst++; + } + + return 0; +} + +static int is_badblock(int pagenumber) +{ + int page = pagenumber; + u32 badblock; + u32 *src; + + /* Check the first two pages for bad block markers */ + for (page = pagenumber; page < pagenumber + 2; page++) { + nfc_nand_read_page(page); + + src = (u32 *)&nfc->spare_area[0][0]; + + /* + * IMPORTANT NOTE: The nand flash controller uses a non- + * standard layout for large page devices. This can + * affect the position of the bad block marker. + */ + /* Get the bad block marker */ + badblock = readl(&src[CONFIG_SYS_NAND_BAD_BLOCK_POS / 4]); + badblock >>= 8 * (CONFIG_SYS_NAND_BAD_BLOCK_POS % 4); + badblock &= 0xff; + + /* bad block marker verify */ + if (badblock != 0xff) + return 1; /* potential bad block */ + } + + return 0; +} + +static int nand_load(unsigned int from, unsigned int size, unsigned char *buf) +{ + int i; + unsigned int page; + unsigned int maxpages = CONFIG_SYS_NAND_SIZE / + CONFIG_SYS_NAND_PAGE_SIZE; + + nfc_nand_init(); + + /* Convert to page number */ + page = from / CONFIG_SYS_NAND_PAGE_SIZE; + i = 0; + + while (i < size / CONFIG_SYS_NAND_PAGE_SIZE) { + if (nfc_read_page(page, buf) < 0) + return -1; + + page++; + i++; + buf = buf + CONFIG_SYS_NAND_PAGE_SIZE; + + /* + * Check if we have crossed a block boundary, and if so + * check for bad block. + */ + if (!(page % CONFIG_SYS_NAND_PAGE_COUNT)) { + /* + * Yes, new block. See if this block is good. If not, + * loop until we find a good block. + */ + while (is_badblock(page)) { + page = page + CONFIG_SYS_NAND_PAGE_COUNT; + /* Check i we've reached the end of flash. */ + if (page >= maxpages) + return -1; + } + } + } + + return 0; +} + +/* + * The main entry for NAND booting. It's necessary that SDRAM is already + * configured and available since this code loads the main U-Boot image + * from NAND into SDRAM and starts it from there. + */ +void nand_boot(void) +{ + __attribute__((noreturn)) void (*uboot)(void); + + /* + * CONFIG_SYS_NAND_U_BOOT_OFFS and CONFIG_SYS_NAND_U_BOOT_SIZE must + * be aligned to full pages + */ + if (!nand_load(CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE, + (uchar *)CONFIG_SYS_NAND_U_BOOT_DST)) { + /* Copy from NAND successful, start U-boot */ + uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START; + uboot(); + } else { + /* Unrecoverable error when copying from NAND */ + hang(); + } +} + +/* + * Called in case of an exception. + */ +void hang(void) +{ + /* Loop forever */ + while (1) ; +} diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index ff2d348..4727f9c 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -416,11 +416,13 @@ int nand_unlock(struct mtd_info *mtd, loff_t start, size_t length, * @param nand NAND device * @param offset offset in flash * @param length image length + * @param used length of flash needed for the requested length * @return 0 if the image fits and there are no bad blocks * 1 if the image fits, but there are bad blocks * -1 if the image does not fit */ -static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length) +static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length, + size_t *used) { size_t len_excl_bad = 0; int ret = 0; @@ -442,8 +444,13 @@ static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length) ret = 1; offset += block_len; + *used += block_len; } + /* If the length is not a multiple of block_len, adjust. */ + if (len_excl_bad > length) + *used -= (len_excl_bad - length); + return ret; } @@ -476,23 +483,36 @@ static size_t drop_ffs(const nand_info_t *nand, const u_char *buf, * Write image to NAND flash. * Blocks that are marked bad are skipped and the is written to the next * block instead as long as the image is short enough to fit even after - * skipping the bad blocks. + * skipping the bad blocks. Due to bad blocks we may not be able to + * perform the requested write. In the case where the write would + * extend beyond the end of the NAND device, both length and actual (if + * not NULL) are set to 0. In the case where the write would extend + * beyond the limit we are passed, length is set to 0 and actual is set + * to the required length. * * @param nand NAND device * @param offset offset in flash * @param length buffer length + * @param actual set to size required to write length worth of + * buffer or 0 on error, if not NULL + * @param lim maximum size that actual may be in order to not + * exceed the buffer * @param buffer buffer to read from * @param flags flags modifying the behaviour of the write to NAND * @return 0 in case of success */ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, - u_char *buffer, int flags) + size_t *actual, loff_t lim, u_char *buffer, int flags) { int rval = 0, blocksize; size_t left_to_write = *length; + size_t used_for_write = 0; u_char *p_buffer = buffer; int need_skip; + if (actual) + *actual = 0; + #ifdef CONFIG_CMD_NAND_YAFFS if (flags & WITH_YAFFS_OOB) { if (flags & ~WITH_YAFFS_OOB) @@ -529,13 +549,23 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, return -EINVAL; } - need_skip = check_skip_len(nand, offset, *length); + need_skip = check_skip_len(nand, offset, *length, &used_for_write); + + if (actual) + *actual = used_for_write; + if (need_skip < 0) { printf("Attempt to write outside the flash area\n"); *length = 0; return -EINVAL; } + if (used_for_write > lim) { + puts("Size of write exceeds partition or device limit\n"); + *length = 0; + return -EFBIG; + } + if (!need_skip && !(flags & WITH_DROP_FFS)) { rval = nand_write(nand, offset, length, buffer); if (rval == 0) @@ -626,36 +656,58 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, * * Read image from NAND flash. * Blocks that are marked bad are skipped and the next block is read - * instead as long as the image is short enough to fit even after skipping the - * bad blocks. + * instead as long as the image is short enough to fit even after + * skipping the bad blocks. Due to bad blocks we may not be able to + * perform the requested read. In the case where the read would extend + * beyond the end of the NAND device, both length and actual (if not + * NULL) are set to 0. In the case where the read would extend beyond + * the limit we are passed, length is set to 0 and actual is set to the + * required length. * * @param nand NAND device * @param offset offset in flash * @param length buffer length, on return holds number of read bytes + * @param actual set to size required to read length worth of buffer or 0 + * on error, if not NULL + * @param lim maximum size that actual may be in order to not exceed the + * buffer * @param buffer buffer to write to * @return 0 in case of success */ int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, - u_char *buffer) + size_t *actual, loff_t lim, u_char *buffer) { int rval; size_t left_to_read = *length; + size_t used_for_read = 0; u_char *p_buffer = buffer; int need_skip; if ((offset & (nand->writesize - 1)) != 0) { printf("Attempt to read non page-aligned data\n"); *length = 0; + if (actual) + *actual = 0; return -EINVAL; } - need_skip = check_skip_len(nand, offset, *length); + need_skip = check_skip_len(nand, offset, *length, &used_for_read); + + if (actual) + *actual = used_for_read; + if (need_skip < 0) { printf("Attempt to read outside the flash area\n"); *length = 0; return -EINVAL; } + if (used_for_read > lim) { + puts("Size of read exceeds partition or device limit\n"); + *length = 0; + return -EFBIG; + } + if (!need_skip) { rval = nand_read(nand, offset, length, buffer); if (!rval || rval == -EUCLEAN) diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index 6ebbb5e..213d2c9 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c @@ -156,7 +156,7 @@ static uint8_t ndfc_read_byte(struct mtd_info *mtd) struct nand_chip *chip = mtd->priv; -#ifdef CONFIG_SYS_NDFC_16BIT +#ifdef CONFIG_SYS_NAND_BUSWIDTH_16BIT return (uint8_t) readw(chip->IO_ADDR_R); #else return readb(chip->IO_ADDR_R); @@ -218,7 +218,7 @@ int board_nand_init(struct nand_chip *nand) nand->ecc.bytes = 3; nand->select_chip = ndfc_select_chip; -#ifdef CONFIG_SYS_NDFC_16BIT +#ifdef CONFIG_SYS_NAND_BUSWIDTH_16BIT nand->options |= NAND_BUSWIDTH_16; #endif diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c index cee394e..bc1bcad 100644 --- a/drivers/mtd/nand/omap_gpmc.c +++ b/drivers/mtd/nand/omap_gpmc.c @@ -25,8 +25,10 @@ #include <asm/io.h> #include <asm/errno.h> #include <asm/arch/mem.h> -#include <asm/arch/omap_gpmc.h> +#include <asm/arch/cpu.h> +#include <asm/omap_gpmc.h> #include <linux/mtd/nand_ecc.h> +#include <linux/bch.h> #include <linux/compiler.h> #include <nand.h> #ifdef CONFIG_AM33XX @@ -36,6 +38,8 @@ static uint8_t cs; static __maybe_unused struct nand_ecclayout hw_nand_oob = GPMC_NAND_HW_ECC_LAYOUT; +static __maybe_unused struct nand_ecclayout hw_bch8_nand_oob = + GPMC_NAND_HW_BCH8_ECC_LAYOUT; /* * omap_nand_hwcontrol - Set the address pointers corretly for the @@ -238,13 +242,13 @@ static void __maybe_unused omap_enable_hwecc(struct mtd_info *mtd, int32_t mode) } /* - * BCH8 support (needs ELM and thus AM33xx-only) + * Generic BCH interface */ -#ifdef CONFIG_AM33XX struct nand_bch_priv { uint8_t mode; uint8_t type; uint8_t nibbles; + struct bch_control *control; }; /* bch types */ @@ -252,21 +256,146 @@ struct nand_bch_priv { #define ECC_BCH8 1 #define ECC_BCH16 2 +/* GPMC ecc engine settings */ +#define BCH_WRAPMODE_1 1 /* BCH wrap mode 1 */ +#define BCH_WRAPMODE_6 6 /* BCH wrap mode 6 */ + /* BCH nibbles for diff bch levels */ #define NAND_ECC_HW_BCH ((uint8_t)(NAND_ECC_HW_OOB_FIRST) + 1) #define ECC_BCH4_NIBBLES 13 #define ECC_BCH8_NIBBLES 26 #define ECC_BCH16_NIBBLES 52 -static struct nand_ecclayout hw_bch8_nand_oob = GPMC_NAND_HW_BCH8_ECC_LAYOUT; - -static struct nand_bch_priv bch_priv = { +/* + * This can be a single instance cause all current users have only one NAND + * with nearly the same setup (BCH8, some with ELM and others with sw BCH + * library). + * When some users with other BCH strength will exists this have to change! + */ +static __maybe_unused struct nand_bch_priv bch_priv = { .mode = NAND_ECC_HW_BCH, .type = ECC_BCH8, - .nibbles = ECC_BCH8_NIBBLES + .nibbles = ECC_BCH8_NIBBLES, + .control = NULL }; /* + * omap_hwecc_init_bch - Initialize the BCH Hardware ECC for NAND flash in + * GPMC controller + * @mtd: MTD device structure + * @mode: Read/Write mode + */ +__maybe_unused +static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode) +{ + uint32_t val; + uint32_t dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1; +#ifdef CONFIG_AM33XX + uint32_t unused_length = 0; +#endif + uint32_t wr_mode = BCH_WRAPMODE_6; + struct nand_bch_priv *bch = chip->priv; + + /* Clear the ecc result registers, select ecc reg as 1 */ + writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control); + +#ifdef CONFIG_AM33XX + wr_mode = BCH_WRAPMODE_1; + + switch (bch->nibbles) { + case ECC_BCH4_NIBBLES: + unused_length = 3; + break; + case ECC_BCH8_NIBBLES: + unused_length = 2; + break; + case ECC_BCH16_NIBBLES: + unused_length = 0; + break; + } + + /* + * This is ecc_size_config for ELM mode. + * Here we are using different settings for read and write access and + * also depending on BCH strength. + */ + switch (mode) { + case NAND_ECC_WRITE: + /* write access only setup eccsize1 config */ + val = ((unused_length + bch->nibbles) << 22); + break; + + case NAND_ECC_READ: + default: + /* + * by default eccsize0 selected for ecc1resultsize + * eccsize0 config. + */ + val = (bch->nibbles << 12); + /* eccsize1 config */ + val |= (unused_length << 22); + break; + } +#else + /* + * This ecc_size_config setting is for BCH sw library. + * + * Note: we only support BCH8 currently with BCH sw library! + * Should be really easy to adobt to BCH4, however some omap3 have + * flaws with BCH4. + * + * Here we are using wrapping mode 6 both for reading and writing, with: + * size0 = 0 (no additional protected byte in spare area) + * size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area) + */ + val = (32 << 22) | (0 << 12); +#endif + /* ecc size configuration */ + writel(val, &gpmc_cfg->ecc_size_config); + + /* + * Configure the ecc engine in gpmc + * We assume 512 Byte sector pages for access to NAND. + */ + val = (1 << 16); /* enable BCH mode */ + val |= (bch->type << 12); /* setup BCH type */ + val |= (wr_mode << 8); /* setup wrapping mode */ + val |= (dev_width << 7); /* setup device width (16 or 8 bit) */ + val |= (cs << 1); /* setup chip select to work on */ + debug("set ECC_CONFIG=0x%08x\n", val); + writel(val, &gpmc_cfg->ecc_config); +} + +/* + * omap_enable_ecc_bch - This function enables the bch h/w ecc functionality + * @mtd: MTD device structure + * @mode: Read/Write mode + */ +__maybe_unused +static void omap_enable_ecc_bch(struct mtd_info *mtd, int32_t mode) +{ + struct nand_chip *chip = mtd->priv; + + omap_hwecc_init_bch(chip, mode); + /* enable ecc */ + writel((readl(&gpmc_cfg->ecc_config) | 0x1), &gpmc_cfg->ecc_config); +} + +/* + * omap_ecc_disable - Disable H/W ECC calculation + * + * @mtd: MTD device structure + */ +static void __maybe_unused omap_ecc_disable(struct mtd_info *mtd) +{ + writel((readl(&gpmc_cfg->ecc_config) & ~0x1), &gpmc_cfg->ecc_config); +} + +/* + * BCH8 support (needs ELM and thus AM33xx-only) + */ +#ifdef CONFIG_AM33XX +/* * omap_read_bch8_result - Read BCH result for BCH8 level * * @mtd: MTD device structure @@ -305,18 +434,6 @@ static void omap_read_bch8_result(struct mtd_info *mtd, uint8_t big_endian, } /* - * omap_ecc_disable - Disable H/W ECC calculation - * - * @mtd: MTD device structure - * - */ -static void omap_ecc_disable(struct mtd_info *mtd) -{ - writel((readl(&gpmc_cfg->ecc_config) & ~0x1), - &gpmc_cfg->ecc_config); -} - -/* * omap_rotate_ecc_bch - Rotate the syndrome bytes * * @mtd: MTD device structure @@ -467,76 +584,6 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat, return 0; } -/* - * omap_hwecc_init_bch - Initialize the BCH Hardware ECC for NAND flash in - * GPMC controller - * @mtd: MTD device structure - * @mode: Read/Write mode - */ -static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode) -{ - uint32_t val, dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1; - uint32_t unused_length = 0; - struct nand_bch_priv *bch = chip->priv; - - switch (bch->nibbles) { - case ECC_BCH4_NIBBLES: - unused_length = 3; - break; - case ECC_BCH8_NIBBLES: - unused_length = 2; - break; - case ECC_BCH16_NIBBLES: - unused_length = 0; - break; - } - - /* Clear the ecc result registers, select ecc reg as 1 */ - writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control); - - switch (mode) { - case NAND_ECC_WRITE: - /* eccsize1 config */ - val = ((unused_length + bch->nibbles) << 22); - break; - - case NAND_ECC_READ: - default: - /* by default eccsize0 selected for ecc1resultsize */ - /* eccsize0 config */ - val = (bch->nibbles << 12); - /* eccsize1 config */ - val |= (unused_length << 22); - break; - } - /* ecc size configuration */ - writel(val, &gpmc_cfg->ecc_size_config); - /* by default 512bytes sector page is selected */ - /* set bch mode */ - val = (1 << 16); - /* bch4 / bch8 / bch16 */ - val |= (bch->type << 12); - /* set wrap mode to 1 */ - val |= (1 << 8); - val |= (dev_width << 7); - val |= (cs << 1); - writel(val, &gpmc_cfg->ecc_config); -} - -/* - * omap_enable_ecc_bch- This function enables the bch h/w ecc functionality - * @mtd: MTD device structure - * @mode: Read/Write mode - * - */ -static void omap_enable_ecc_bch(struct mtd_info *mtd, int32_t mode) -{ - struct nand_chip *chip = mtd->priv; - - omap_hwecc_init_bch(chip, mode); - /* enable ecc */ - writel((readl(&gpmc_cfg->ecc_config) | 0x1), &gpmc_cfg->ecc_config); -} /** * omap_read_page_bch - hardware ecc based page read function @@ -601,15 +648,137 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip, } #endif /* CONFIG_AM33XX */ -#ifndef CONFIG_SPL_BUILD /* - * omap_nand_switch_ecc - switch the ECC operation b/w h/w ecc and s/w ecc. - * The default is to come up on s/w ecc + * OMAP3 BCH8 support (with BCH library) + */ +#ifdef CONFIG_NAND_OMAP_BCH8 +/* + * omap_calculate_ecc_bch - Read BCH ECC result * - * @hardware - 1 -switch to h/w ecc, 0 - s/w ecc + * @mtd: MTD device structure + * @dat: The pointer to data on which ecc is computed (unused here) + * @ecc: The ECC output buffer + */ +static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat, + uint8_t *ecc) +{ + int ret = 0; + size_t i; + unsigned long nsectors, val1, val2, val3, val4; + + nsectors = ((readl(&gpmc_cfg->ecc_config) >> 4) & 0x7) + 1; + + for (i = 0; i < nsectors; i++) { + /* Read hw-computed remainder */ + val1 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[0]); + val2 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[1]); + val3 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[2]); + val4 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[3]); + + /* + * Add constant polynomial to remainder, in order to get an ecc + * sequence of 0xFFs for a buffer filled with 0xFFs. + */ + *ecc++ = 0xef ^ (val4 & 0xFF); + *ecc++ = 0x51 ^ ((val3 >> 24) & 0xFF); + *ecc++ = 0x2e ^ ((val3 >> 16) & 0xFF); + *ecc++ = 0x09 ^ ((val3 >> 8) & 0xFF); + *ecc++ = 0xed ^ (val3 & 0xFF); + *ecc++ = 0x93 ^ ((val2 >> 24) & 0xFF); + *ecc++ = 0x9a ^ ((val2 >> 16) & 0xFF); + *ecc++ = 0xc2 ^ ((val2 >> 8) & 0xFF); + *ecc++ = 0x97 ^ (val2 & 0xFF); + *ecc++ = 0x79 ^ ((val1 >> 24) & 0xFF); + *ecc++ = 0xe5 ^ ((val1 >> 16) & 0xFF); + *ecc++ = 0x24 ^ ((val1 >> 8) & 0xFF); + *ecc++ = 0xb5 ^ (val1 & 0xFF); + } + + /* + * Stop reading anymore ECC vals and clear old results + * enable will be called if more reads are required + */ + omap_ecc_disable(mtd); + + return ret; +} + +/** + * omap_correct_data_bch - Decode received data and correct errors + * @mtd: MTD device structure + * @data: page data + * @read_ecc: ecc read from nand flash + * @calc_ecc: ecc read from HW ECC registers + */ +static int omap_correct_data_bch(struct mtd_info *mtd, u_char *data, + u_char *read_ecc, u_char *calc_ecc) +{ + int i, count; + /* cannot correct more than 8 errors */ + unsigned int errloc[8]; + struct nand_chip *chip = mtd->priv; + struct nand_bch_priv *chip_priv = chip->priv; + struct bch_control *bch = chip_priv->control; + + count = decode_bch(bch, NULL, 512, read_ecc, calc_ecc, NULL, errloc); + if (count > 0) { + /* correct errors */ + for (i = 0; i < count; i++) { + /* correct data only, not ecc bytes */ + if (errloc[i] < 8*512) + data[errloc[i]/8] ^= 1 << (errloc[i] & 7); + printf("corrected bitflip %u\n", errloc[i]); +#ifdef DEBUG + puts("read_ecc: "); + /* + * BCH8 have 13 bytes of ECC; BCH4 needs adoption + * here! + */ + for (i = 0; i < 13; i++) + printf("%02x ", read_ecc[i]); + puts("\n"); + puts("calc_ecc: "); + for (i = 0; i < 13; i++) + printf("%02x ", calc_ecc[i]); + puts("\n"); +#endif + } + } else if (count < 0) { + puts("ecc unrecoverable error\n"); + } + return count; +} + +/** + * omap_free_bch - Release BCH ecc resources + * @mtd: MTD device structure + */ +static void __maybe_unused omap_free_bch(struct mtd_info *mtd) +{ + struct nand_chip *chip = mtd->priv; + struct nand_bch_priv *chip_priv = chip->priv; + struct bch_control *bch = NULL; + + if (chip_priv) + bch = chip_priv->control; + + if (bch) { + free_bch(bch); + chip_priv->control = NULL; + } +} +#endif /* CONFIG_NAND_OMAP_BCH8 */ + +#ifndef CONFIG_SPL_BUILD +/* + * omap_nand_switch_ecc - switch the ECC operation between different engines + * (h/w and s/w) and different algorithms (hamming and BCHx) * + * @hardware - true if one of the HW engines should be used + * @eccstrength - the number of bits that could be corrected + * (1 - hamming, 4 - BCH4, 8 - BCH8, 16 - BCH16) */ -void omap_nand_switch_ecc(int32_t hardware) +void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength) { struct nand_chip *nand; struct mtd_info *mtd; @@ -627,6 +796,7 @@ void omap_nand_switch_ecc(int32_t hardware) nand->options |= NAND_OWN_BUFFERS; /* Reset ecc interface */ + nand->ecc.mode = NAND_ECC_NONE; nand->ecc.read_page = NULL; nand->ecc.write_page = NULL; nand->ecc.read_oob = NULL; @@ -636,28 +806,35 @@ void omap_nand_switch_ecc(int32_t hardware) nand->ecc.calculate = NULL; /* Setup the ecc configurations again */ - if (hardware == 1) { - nand->ecc.mode = NAND_ECC_HW; - nand->ecc.layout = &hw_nand_oob; - nand->ecc.size = 512; - nand->ecc.bytes = 3; - nand->ecc.hwctl = omap_enable_hwecc; - nand->ecc.correct = omap_correct_data; - nand->ecc.calculate = omap_calculate_ecc; - omap_hwecc_init(nand); - printf("HW ECC selected\n"); + if (hardware) { + if (eccstrength == 1) { + nand->ecc.mode = NAND_ECC_HW; + nand->ecc.layout = &hw_nand_oob; + nand->ecc.size = 512; + nand->ecc.bytes = 3; + nand->ecc.hwctl = omap_enable_hwecc; + nand->ecc.correct = omap_correct_data; + nand->ecc.calculate = omap_calculate_ecc; + omap_hwecc_init(nand); + printf("1-bit hamming HW ECC selected\n"); + } +#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8) + else if (eccstrength == 8) { + nand->ecc.mode = NAND_ECC_HW; + nand->ecc.layout = &hw_bch8_nand_oob; + nand->ecc.size = 512; #ifdef CONFIG_AM33XX - } else if (hardware == 2) { - nand->ecc.mode = NAND_ECC_HW; - nand->ecc.layout = &hw_bch8_nand_oob; - nand->ecc.size = 512; - nand->ecc.bytes = 14; - nand->ecc.read_page = omap_read_page_bch; - nand->ecc.hwctl = omap_enable_ecc_bch; - nand->ecc.correct = omap_correct_data_bch; - nand->ecc.calculate = omap_calculate_ecc_bch; - omap_hwecc_init_bch(nand, NAND_ECC_READ); - printf("HW BCH8 selected\n"); + nand->ecc.bytes = 14; + nand->ecc.read_page = omap_read_page_bch; +#else + nand->ecc.bytes = 13; +#endif + nand->ecc.hwctl = omap_enable_ecc_bch; + nand->ecc.correct = omap_correct_data_bch; + nand->ecc.calculate = omap_calculate_ecc_bch; + omap_hwecc_init_bch(nand, NAND_ECC_READ); + printf("8-bit BCH HW ECC selected\n"); + } #endif } else { nand->ecc.mode = NAND_ECC_SOFT; @@ -731,16 +908,28 @@ int board_nand_init(struct nand_chip *nand) nand->chip_delay = 100; +#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8) #ifdef CONFIG_AM33XX + /* AM33xx uses the ELM */ /* required in case of BCH */ elm_init(); - +#else + /* + * Whereas other OMAP based SoC do not have the ELM, they use the BCH + * SW library. + */ + bch_priv.control = init_bch(13, 8, 0x201b /* hw polynominal */); + if (!bch_priv.control) { + puts("Could not init_bch()\n"); + return -ENODEV; + } +#endif /* BCH info that will be correct for SPL or overridden otherwise. */ nand->priv = &bch_priv; #endif /* Default ECC mode */ -#ifdef CONFIG_AM33XX +#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8) nand->ecc.mode = NAND_ECC_HW; nand->ecc.layout = &hw_bch8_nand_oob; nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE; @@ -748,7 +937,9 @@ int board_nand_init(struct nand_chip *nand) nand->ecc.hwctl = omap_enable_ecc_bch; nand->ecc.correct = omap_correct_data_bch; nand->ecc.calculate = omap_calculate_ecc_bch; +#ifdef CONFIG_AM33XX nand->ecc.read_page = omap_read_page_bch; +#endif omap_hwecc_init_bch(nand, NAND_ECC_READ); #else #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_NAND_SOFTECC) diff --git a/drivers/mtd/nand/s3c64xx.c b/drivers/mtd/nand/s3c64xx.c deleted file mode 100644 index 87f0341..0000000 --- a/drivers/mtd/nand/s3c64xx.c +++ /dev/null @@ -1,295 +0,0 @@ -/* - * (C) Copyright 2006 DENX Software Engineering - * - * Implementation for U-Boot 1.1.6 by Samsung - * - * (C) Copyright 2008 - * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> - -#include <nand.h> -#include <linux/mtd/nand.h> - -#include <asm/arch/s3c6400.h> - -#include <asm/io.h> -#include <asm/errno.h> - -#define MAX_CHIPS 2 -static int nand_cs[MAX_CHIPS] = {0, 1}; - -#ifdef CONFIG_NAND_SPL -#define printf(arg...) do {} while (0) -#endif - -/* Nand flash definition values by jsgood */ -#ifdef S3C_NAND_DEBUG -/* - * Function to print out oob buffer for debugging - * Written by jsgood - */ -static void print_oob(const char *header, struct mtd_info *mtd) -{ - int i; - struct nand_chip *chip = mtd->priv; - - printf("%s:\t", header); - - for (i = 0; i < 64; i++) - printf("%02x ", chip->oob_poi[i]); - - printf("\n"); -} -#endif /* S3C_NAND_DEBUG */ - -static void s3c_nand_select_chip(struct mtd_info *mtd, int chip) -{ - int ctrl = readl(NFCONT); - - switch (chip) { - case -1: - ctrl |= 6; - break; - case 0: - ctrl &= ~2; - break; - case 1: - ctrl &= ~4; - break; - default: - return; - } - - writel(ctrl, NFCONT); -} - -/* - * Hardware specific access to control-lines function - * Written by jsgood - */ -static void s3c_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) -{ - struct nand_chip *this = mtd->priv; - - if (ctrl & NAND_CTRL_CHANGE) { - if (ctrl & NAND_CLE) - this->IO_ADDR_W = (void __iomem *)NFCMMD; - else if (ctrl & NAND_ALE) - this->IO_ADDR_W = (void __iomem *)NFADDR; - else - this->IO_ADDR_W = (void __iomem *)NFDATA; - if (ctrl & NAND_NCE) - s3c_nand_select_chip(mtd, *(int *)this->priv); - else - s3c_nand_select_chip(mtd, -1); - } - - if (cmd != NAND_CMD_NONE) - writeb(cmd, this->IO_ADDR_W); -} - -/* - * Function for checking device ready pin - * Written by jsgood - */ -static int s3c_nand_device_ready(struct mtd_info *mtdinfo) -{ - return !!(readl(NFSTAT) & NFSTAT_RnB); -} - -#ifdef CONFIG_SYS_S3C_NAND_HWECC -/* - * This function is called before encoding ecc codes to ready ecc engine. - * Written by jsgood - */ -static void s3c_nand_enable_hwecc(struct mtd_info *mtd, int mode) -{ - u_long nfcont, nfconf; - - /* - * The original driver used 4-bit ECC for "new" MLC chips, i.e., for - * those with non-zero ID[3][3:2], which anyway only holds for ST - * (Numonyx) chips - */ - nfconf = readl(NFCONF) & ~NFCONF_ECC_4BIT; - - writel(nfconf, NFCONF); - - /* Initialize & unlock */ - nfcont = readl(NFCONT); - nfcont |= NFCONT_INITECC; - nfcont &= ~NFCONT_MECCLOCK; - - if (mode == NAND_ECC_WRITE) - nfcont |= NFCONT_ECC_ENC; - else if (mode == NAND_ECC_READ) - nfcont &= ~NFCONT_ECC_ENC; - - writel(nfcont, NFCONT); -} - -/* - * This function is called immediately after encoding ecc codes. - * This function returns encoded ecc codes. - * Written by jsgood - */ -static int s3c_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, - u_char *ecc_code) -{ - u_long nfcont, nfmecc0; - - /* Lock */ - nfcont = readl(NFCONT); - nfcont |= NFCONT_MECCLOCK; - writel(nfcont, NFCONT); - - nfmecc0 = readl(NFMECC0); - - ecc_code[0] = nfmecc0 & 0xff; - ecc_code[1] = (nfmecc0 >> 8) & 0xff; - ecc_code[2] = (nfmecc0 >> 16) & 0xff; - ecc_code[3] = (nfmecc0 >> 24) & 0xff; - - return 0; -} - -/* - * This function determines whether read data is good or not. - * If SLC, must write ecc codes to controller before reading status bit. - * If MLC, status bit is already set, so only reading is needed. - * If status bit is good, return 0. - * If correctable errors occured, do that. - * If uncorrectable errors occured, return -1. - * Written by jsgood - */ -static int s3c_nand_correct_data(struct mtd_info *mtd, u_char *dat, - u_char *read_ecc, u_char *calc_ecc) -{ - int ret = -1; - u_long nfestat0, nfmeccdata0, nfmeccdata1, err_byte_addr; - u_char err_type, repaired; - - /* SLC: Write ecc to compare */ - nfmeccdata0 = (calc_ecc[1] << 16) | calc_ecc[0]; - nfmeccdata1 = (calc_ecc[3] << 16) | calc_ecc[2]; - writel(nfmeccdata0, NFMECCDATA0); - writel(nfmeccdata1, NFMECCDATA1); - - /* Read ecc status */ - nfestat0 = readl(NFESTAT0); - err_type = nfestat0 & 0x3; - - switch (err_type) { - case 0: /* No error */ - ret = 0; - break; - - case 1: - /* - * 1 bit error (Correctable) - * (nfestat0 >> 7) & 0x7ff :error byte number - * (nfestat0 >> 4) & 0x7 :error bit number - */ - err_byte_addr = (nfestat0 >> 7) & 0x7ff; - repaired = dat[err_byte_addr] ^ (1 << ((nfestat0 >> 4) & 0x7)); - - printf("S3C NAND: 1 bit error detected at byte %ld. " - "Correcting from 0x%02x to 0x%02x...OK\n", - err_byte_addr, dat[err_byte_addr], repaired); - - dat[err_byte_addr] = repaired; - - ret = 1; - break; - - case 2: /* Multiple error */ - case 3: /* ECC area error */ - printf("S3C NAND: ECC uncorrectable error detected. " - "Not correctable.\n"); - ret = -1; - break; - } - - return ret; -} -#endif /* CONFIG_SYS_S3C_NAND_HWECC */ - -/* - * Board-specific NAND initialization. The following members of the - * argument are board-specific (per include/linux/mtd/nand.h): - * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device - * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device - * - hwcontrol: hardwarespecific function for accesing control-lines - * - dev_ready: hardwarespecific function for accesing device ready/busy line - * - enable_hwecc?: function to enable (reset) hardware ecc generator. Must - * only be provided if a hardware ECC is available - * - eccmode: mode of ecc, see defines - * - chip_delay: chip dependent delay for transfering data from array to - * read regs (tR) - * - options: various chip options. They can partly be set to inform - * nand_scan about special functionality. See the defines for further - * explanation - * Members with a "?" were not set in the merged testing-NAND branch, - * so they are not set here either. - */ -int board_nand_init(struct nand_chip *nand) -{ - static int chip_n; - - if (chip_n >= MAX_CHIPS) - return -ENODEV; - - NFCONT_REG = (NFCONT_REG & ~NFCONT_WP) | NFCONT_ENABLE | 0x6; - - nand->IO_ADDR_R = (void __iomem *)NFDATA; - nand->IO_ADDR_W = (void __iomem *)NFDATA; - nand->cmd_ctrl = s3c_nand_hwcontrol; - nand->dev_ready = s3c_nand_device_ready; - nand->select_chip = s3c_nand_select_chip; - nand->options = 0; -#ifdef CONFIG_NAND_SPL - nand->read_byte = nand_read_byte; - nand->write_buf = nand_write_buf; - nand->read_buf = nand_read_buf; -#endif - -#ifdef CONFIG_SYS_S3C_NAND_HWECC - nand->ecc.hwctl = s3c_nand_enable_hwecc; - nand->ecc.calculate = s3c_nand_calculate_ecc; - nand->ecc.correct = s3c_nand_correct_data; - - /* - * If you get more than 1 NAND-chip with different page-sizes on the - * board one day, it will get more complicated... - */ - nand->ecc.mode = NAND_ECC_HW; - nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE; - nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES; -#else - nand->ecc.mode = NAND_ECC_SOFT; -#endif /* ! CONFIG_SYS_S3C_NAND_HWECC */ - - nand->priv = nand_cs + chip_n++; - - return 0; -} diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 1a7b40e..858e322 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -632,10 +632,6 @@ static int onenand_check_bufferram(struct mtd_info *mtd, loff_t addr) int blockpage, found = 0; unsigned int i; -#ifdef CONFIG_S3C64XX - return 0; -#endif - if (ONENAND_IS_2PLANE(this)) blockpage = onenand_get_2x_blockpage(mtd, addr); else diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c index 0d94ea5..5eb2b3a 100644 --- a/drivers/mtd/onenand/samsung.c +++ b/drivers/mtd/onenand/samsung.c @@ -1,5 +1,5 @@ /* - * S3C64XX/S5PC100 OneNAND driver at U-Boot + * S5PC100 OneNAND driver at U-Boot * * Copyright (C) 2008-2009 Samsung Electronics * Kyungmin Park <kyungmin.park@samsung.com> @@ -62,12 +62,7 @@ do { \ #define ONENAND_MAIN_SPARE_ACCESS 0x16 #define ONENAND_PIPELINE_READ 0x4000 -#if defined(CONFIG_S3C64XX) -#define MAP_00 (0x0 << 24) -#define MAP_01 (0x1 << 24) -#define MAP_10 (0x2 << 24) -#define MAP_11 (0x3 << 24) -#elif defined(CONFIG_S5P) +#if defined(CONFIG_S5P) #define MAP_00 (0x0 << 26) #define MAP_01 (0x1 << 26) #define MAP_10 (0x2 << 26) @@ -116,12 +111,7 @@ static void s3c_write_cmd(int value, unsigned int cmd) * return the buffer address on the memory device * It will be combined with CMD_MAP_XX */ -#if defined(CONFIG_S3C64XX) -static unsigned int s3c_mem_addr(int fba, int fpa, int fsa) -{ - return (fba << 12) | (fpa << 6) | (fsa << 4); -} -#elif defined(CONFIG_S5P) +#if defined(CONFIG_S5P) static unsigned int s3c_mem_addr(int fba, int fpa, int fsa) { return (fba << 13) | (fpa << 7) | (fsa << 5); @@ -550,45 +540,6 @@ static void s3c_onenand_unlock_all(struct mtd_info *mtd) s3c_onenand_check_lock_status(mtd); } -#ifdef CONFIG_S3C64XX -static void s3c_set_width_regs(struct onenand_chip *this) -{ - int dev_id, density; - int fba, fpa, fsa; - int dbs_dfs; - - dev_id = DEVICE_ID0_REG; - - density = (dev_id >> ONENAND_DEVICE_DENSITY_SHIFT) & 0xf; - dbs_dfs = !!(dev_id & ONENAND_DEVICE_IS_DDP); - - fba = density + 7; - if (dbs_dfs) - fba--; /* Decrease the fba */ - fpa = 6; - if (density >= ONENAND_DEVICE_DENSITY_512Mb) - fsa = 2; - else - fsa = 1; - - DPRINTK("FBA %lu, FPA %lu, FSA %lu, DDP %lu", - FBA_WIDTH0_REG, FPA_WIDTH0_REG, FSA_WIDTH0_REG, - DDP_DEVICE_REG); - - DPRINTK("mem_cfg0 0x%lx, sync mode %lu, " - "dev_page_size %lu, BURST LEN %lu", - MEM_CFG0_REG, SYNC_MODE_REG, - DEV_PAGE_SIZE_REG, BURST_LEN0_REG); - - DEV_PAGE_SIZE_REG = 0x1; - - FBA_WIDTH0_REG = fba; - FPA_WIDTH0_REG = fpa; - FSA_WIDTH0_REG = fsa; - DBS_DFS_WIDTH0_REG = dbs_dfs; -} -#endif - int s5pc110_chip_probe(struct mtd_info *mtd) { return 0; @@ -620,10 +571,7 @@ void s3c_onenand_init(struct mtd_info *mtd) onenand->mtd = mtd; -#if defined(CONFIG_S3C64XX) - onenand->base = (void *)0x70100000; - onenand->ahb_addr = (void *)0x20000000; -#elif defined(CONFIG_S5P) +#if defined(CONFIG_S5P) onenand->base = (void *)0xE7100000; onenand->ahb_addr = (void *)0xB0000000; #endif diff --git a/drivers/mtd/spi/atmel.c b/drivers/mtd/spi/atmel.c index 006f6d5..6a92c4b 100644 --- a/drivers/mtd/spi/atmel.c +++ b/drivers/mtd/spi/atmel.c @@ -480,15 +480,13 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode) return NULL; } - asf = malloc(sizeof(struct atmel_spi_flash)); + asf = spi_flash_alloc(struct atmel_spi_flash, spi, params->name); if (!asf) { debug("SF: Failed to allocate memory\n"); return NULL; } asf->params = params; - asf->flash.spi = spi; - asf->flash.name = params->name; /* Assuming power-of-two page size initially. */ page_size = 1 << params->l2_page_size; @@ -513,7 +511,6 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode) asf->flash.erase = dataflash_erase_at45; page_size += 1 << (params->l2_page_size - 5); } else { - asf->flash.read = spi_flash_cmd_read_fast; asf->flash.write = dataflash_write_p2; asf->flash.erase = dataflash_erase_p2; } @@ -524,9 +521,6 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode) case DF_FAMILY_AT26F: case DF_FAMILY_AT26DF: - asf->flash.read = spi_flash_cmd_read_fast; - asf->flash.write = spi_flash_cmd_write_multi; - asf->flash.erase = spi_flash_cmd_erase; asf->flash.page_size = page_size; asf->flash.sector_size = 4096; /* clear SPRL# bit for locked flash */ diff --git a/drivers/mtd/spi/eon.c b/drivers/mtd/spi/eon.c index 691ed4e..b16e7ab 100644 --- a/drivers/mtd/spi/eon.c +++ b/drivers/mtd/spi/eon.c @@ -46,18 +46,12 @@ struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode) return NULL; } - flash = malloc(sizeof(*flash)); + flash = spi_flash_alloc_base(spi, params->name); if (!flash) { debug("SF: Failed to allocate memory\n"); return NULL; } - flash->spi = spi; - flash->name = params->name; - - flash->write = spi_flash_cmd_write_multi; - flash->erase = spi_flash_cmd_erase; - flash->read = spi_flash_cmd_read_fast; flash->page_size = 256; flash->sector_size = 256 * 16 * 16; flash->size = 256 * 16 diff --git a/drivers/mtd/spi/macronix.c b/drivers/mtd/spi/macronix.c index c97a39d..036c30d 100644 --- a/drivers/mtd/spi/macronix.c +++ b/drivers/mtd/spi/macronix.c @@ -97,18 +97,12 @@ struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode) return NULL; } - flash = malloc(sizeof(*flash)); + flash = spi_flash_alloc_base(spi, params->name); if (!flash) { debug("SF: Failed to allocate memory\n"); return NULL; } - flash->spi = spi; - flash->name = params->name; - - flash->write = spi_flash_cmd_write_multi; - flash->erase = spi_flash_cmd_erase; - flash->read = spi_flash_cmd_read_fast; flash->page_size = 256; flash->sector_size = 256 * 16 * 16; flash->size = flash->sector_size * params->nr_blocks; diff --git a/drivers/mtd/spi/ramtron.c b/drivers/mtd/spi/ramtron.c index 0999781..5299a6d 100644 --- a/drivers/mtd/spi/ramtron.c +++ b/drivers/mtd/spi/ramtron.c @@ -284,15 +284,13 @@ struct spi_flash *spi_fram_probe_ramtron(struct spi_slave *spi, u8 *idcode) return NULL; found: - sn = malloc(sizeof(*sn)); + sn = spi_flash_alloc(struct ramtron_spi_fram, spi, params->name); if (!sn) { debug("SF: Failed to allocate memory\n"); return NULL; } sn->params = params; - sn->flash.spi = spi; - sn->flash.name = params->name; sn->flash.write = ramtron_write; sn->flash.read = ramtron_read; diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c index 9288672..bc558c4 100644 --- a/drivers/mtd/spi/spansion.c +++ b/drivers/mtd/spi/spansion.c @@ -128,18 +128,12 @@ struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode) return NULL; } - flash = malloc(sizeof(*flash)); + flash = spi_flash_alloc_base(spi, params->name); if (!flash) { debug("SF: Failed to allocate memory\n"); return NULL; } - flash->spi = spi; - flash->name = params->name; - - flash->write = spi_flash_cmd_write_multi; - flash->erase = spi_flash_cmd_erase; - flash->read = spi_flash_cmd_read_fast; flash->page_size = 256; flash->sector_size = 256 * params->pages_per_sector; flash->size = flash->sector_size * params->nr_sectors; diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 00aece9..111185a 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -8,6 +8,7 @@ */ #include <common.h> +#include <fdtdec.h> #include <malloc.h> #include <spi.h> #include <spi_flash.h> @@ -15,6 +16,8 @@ #include "spi_flash_internal.h" +DECLARE_GLOBAL_DATA_PTR; + static void spi_flash_addr(u32 addr, u8 *cmd) { /* cmd[0] is actual command */ @@ -87,6 +90,9 @@ int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset, for (actual = 0; actual < len; actual += chunk_len) { chunk_len = min(len - actual, page_size - byte_addr); + if (flash->spi->max_write_size) + chunk_len = min(chunk_len, flash->spi->max_write_size); + cmd[1] = page_addr >> 8; cmd[2] = page_addr; cmd[3] = byte_addr; @@ -111,8 +117,11 @@ int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset, if (ret) break; - page_addr++; - byte_addr = 0; + byte_addr += chunk_len; + if (byte_addr == page_size) { + page_addr++; + byte_addr = 0; + } } debug("SF: program %s %zu bytes @ %#x\n", @@ -140,6 +149,10 @@ int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset, { u8 cmd[5]; + /* Handle memory-mapped SPI */ + if (flash->memory_map) + memcpy(data, flash->memory_map + offset, len); + cmd[0] = CMD_READ_ARRAY_FAST; spi_flash_addr(offset, cmd); cmd[4] = 0x00; @@ -269,6 +282,34 @@ int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr) return 0; } +#ifdef CONFIG_OF_CONTROL +int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) +{ + fdt_addr_t addr; + fdt_size_t size; + int node; + + /* If there is no node, do nothing */ + node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH); + if (node < 0) + return 0; + + addr = fdtdec_get_addr_size(blob, node, "memory-map", &size); + if (addr == FDT_ADDR_T_NONE) { + debug("%s: Cannot decode address\n", __func__); + return 0; + } + + if (flash->size != size) { + debug("%s: Memory map must cover entire device\n", __func__); + return -1; + } + flash->memory_map = (void *)addr; + + return 0; +} +#endif /* CONFIG_OF_CONTROL */ + /* * The following table holds all device probe functions * @@ -385,9 +426,18 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, goto err_manufacturer_probe; } +#ifdef CONFIG_OF_CONTROL + if (spi_flash_decode_fdt(gd->fdt_blob, flash)) { + debug("SF: FDT decode error\n"); + goto err_manufacturer_probe; + } +#endif printf("SF: Detected %s with page size ", flash->name); print_size(flash->sector_size, ", total "); - print_size(flash->size, "\n"); + print_size(flash->size, ""); + if (flash->memory_map) + printf(", mapped at %p", flash->memory_map); + puts("\n"); spi_release_bus(spi); @@ -401,6 +451,31 @@ err_claim_bus: return NULL; } +void *spi_flash_do_alloc(int offset, int size, struct spi_slave *spi, + const char *name) +{ + struct spi_flash *flash; + void *ptr; + + ptr = malloc(size); + if (!ptr) { + debug("SF: Failed to allocate memory\n"); + return NULL; + } + memset(ptr, '\0', size); + flash = (struct spi_flash *)(ptr + offset); + + /* Set up some basic fields - caller will sort out sizes */ + flash->spi = spi; + flash->name = name; + + flash->read = spi_flash_cmd_read_fast; + flash->write = spi_flash_cmd_write_multi; + flash->erase = spi_flash_cmd_erase; + + return flash; +} + void spi_flash_free(struct spi_flash *flash) { spi_free_slave(flash->spi); diff --git a/drivers/mtd/spi/sst.c b/drivers/mtd/spi/sst.c index ced4f24..95f5490 100644 --- a/drivers/mtd/spi/sst.c +++ b/drivers/mtd/spi/sst.c @@ -203,22 +203,16 @@ spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode) return NULL; } - stm = malloc(sizeof(*stm)); + stm = spi_flash_alloc(struct sst_spi_flash, spi, params->name); if (!stm) { debug("SF: Failed to allocate memory\n"); return NULL; } stm->params = params; - stm->flash.spi = spi; - stm->flash.name = params->name; if (stm->params->flags & SST_FEAT_WP) stm->flash.write = sst_write_wp; - else - stm->flash.write = spi_flash_cmd_write_multi; - stm->flash.erase = spi_flash_cmd_erase; - stm->flash.read = spi_flash_cmd_read_fast; stm->flash.page_size = 256; stm->flash.sector_size = 4096; stm->flash.size = stm->flash.sector_size * params->nr_sectors; diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c index 8a19344..2a9972b 100644 --- a/drivers/mtd/spi/stmicro.c +++ b/drivers/mtd/spi/stmicro.c @@ -176,18 +176,12 @@ struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode) return NULL; } - flash = malloc(sizeof(*flash)); + flash = spi_flash_alloc_base(spi, params->name); if (!flash) { debug("SF: Failed to allocate memory\n"); return NULL; } - flash->spi = spi; - flash->name = params->name; - - flash->write = spi_flash_cmd_write_multi; - flash->erase = spi_flash_cmd_erase; - flash->read = spi_flash_cmd_read_fast; flash->page_size = 256; flash->sector_size = 256 * params->pages_per_sector; flash->size = flash->sector_size * params->nr_sectors; diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c index 4418302..2716209 100644 --- a/drivers/mtd/spi/winbond.c +++ b/drivers/mtd/spi/winbond.c @@ -68,6 +68,11 @@ static const struct winbond_spi_flash_params winbond_spi_flash_table[] = { .name = "W25Q80", }, { + .id = 0x6016, + .nr_blocks = 512, + .name = "W25Q32DW", + }, + { .id = 0x6017, .nr_blocks = 128, .name = "W25Q64DW", @@ -92,18 +97,12 @@ struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode) return NULL; } - flash = malloc(sizeof(*flash)); + flash = spi_flash_alloc_base(spi, params->name); if (!flash) { debug("SF: Failed to allocate memory\n"); return NULL; } - flash->spi = spi; - flash->name = params->name; - - flash->write = spi_flash_cmd_write_multi; - flash->erase = spi_flash_cmd_erase; - flash->read = spi_flash_cmd_read_fast; flash->page_size = 256; flash->sector_size = 4096; flash->size = 4096 * 16 * params->nr_blocks; diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index d144ac2..a708162 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -478,19 +478,19 @@ static int attach_by_scanning(struct ubi_device *ubi) err = ubi_eba_init_scan(ubi, si); if (err) - goto out_wl; + goto out_vtbl; err = ubi_wl_init_scan(ubi, si); if (err) - goto out_vtbl; + goto out_eba; ubi_scan_destroy_si(si); return 0; +out_eba: + ubi_eba_close(ubi); out_vtbl: vfree(ubi->vtbl); -out_wl: - ubi_wl_close(ubi); out_si: ubi_scan_destroy_si(si); return err; diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 14c3a5f..044e849 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -59,7 +59,11 @@ #define UBI_NAME_STR "ubi" /* Normal UBI messages */ +#ifdef CONFIG_UBI_SILENCE_MSG +#define ubi_msg(fmt, ...) +#else #define ubi_msg(fmt, ...) printk(KERN_NOTICE "UBI: " fmt "\n", ##__VA_ARGS__) +#endif /* UBI warning messages */ #define ubi_warn(fmt, ...) printk(KERN_WARNING "UBI warning: %s: " fmt "\n", \ __func__, ##__VA_ARGS__) diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 88b867a..d1ba722 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -1538,6 +1538,7 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) if (ubi->avail_pebs < WL_RESERVED_PEBS) { ubi_err("no enough physical eraseblocks (%d, need %d)", ubi->avail_pebs, WL_RESERVED_PEBS); + err = -ENOSPC; goto out_free; } ubi->avail_pebs -= WL_RESERVED_PEBS; diff --git a/drivers/net/armada100_fec.c b/drivers/net/armada100_fec.c index ed7cf20..89ebf0b 100644 --- a/drivers/net/armada100_fec.c +++ b/drivers/net/armada100_fec.c @@ -100,7 +100,7 @@ static int smi_reg_read(const char *devname, u8 phy_addr, u8 phy_reg, } /* wait for the SMI register to become available */ - if (armdfec_phy_timeout(®s->smi, SMI_BUSY, FALSE)) { + if (armdfec_phy_timeout(®s->smi, SMI_BUSY, false)) { printf("ARMD100 FEC: (%s) PHY busy timeout\n", __func__); return -1; } @@ -108,7 +108,7 @@ static int smi_reg_read(const char *devname, u8 phy_addr, u8 phy_reg, writel((phy_addr << 16) | (phy_reg << 21) | SMI_OP_R, ®s->smi); /* now wait for the data to be valid */ - if (armdfec_phy_timeout(®s->smi, SMI_R_VALID, TRUE)) { + if (armdfec_phy_timeout(®s->smi, SMI_R_VALID, true)) { val = readl(®s->smi); printf("ARMD100 FEC: (%s) PHY Read timeout, val=0x%x\n", __func__, val); @@ -143,7 +143,7 @@ static int smi_reg_write(const char *devname, } /* wait for the SMI register to become available */ - if (armdfec_phy_timeout(®s->smi, SMI_BUSY, FALSE)) { + if (armdfec_phy_timeout(®s->smi, SMI_BUSY, false)) { printf("ARMD100 FEC: (%s) PHY busy timeout\n", __func__); return -1; } diff --git a/drivers/net/armada100_fec.h b/drivers/net/armada100_fec.h index e2df4fc..dcac964 100644 --- a/drivers/net/armada100_fec.h +++ b/drivers/net/armada100_fec.h @@ -29,13 +29,6 @@ #ifndef __ARMADA100_FEC_H__ #define __ARMADA100_FEC_H__ -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - #define PORT_NUM 0x0 /* RX & TX descriptor command */ diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c index 93f8417..7a36850 100644 --- a/drivers/net/cpsw.c +++ b/drivers/net/cpsw.c @@ -24,6 +24,7 @@ #include <asm/errno.h> #include <asm/io.h> #include <phy.h> +#include <asm/arch/cpu.h> #define BITMASK(bits) (BIT(bits) - 1) #define PHY_REG_MASK 0x1f diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 8ba98b2..c1863f4 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -313,14 +313,14 @@ void e1000_standby_eeprom(struct e1000_hw *hw) * * hw - Struct containing variables accessed by shared code ****************************************************************************/ -static boolean_t e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw) +static bool e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw) { uint32_t eecd = 0; DEBUGFUNC(); if (hw->mac_type == e1000_ich8lan) - return FALSE; + return false; if (hw->mac_type == e1000_82573 || hw->mac_type == e1000_82574) { eecd = E1000_READ_REG(hw, EECD); @@ -330,9 +330,9 @@ static boolean_t e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw) /* If both bits are set, device is Flash type */ if (eecd == 0x03) - return FALSE; + return false; } - return TRUE; + return true; } /****************************************************************************** @@ -421,8 +421,8 @@ static int32_t e1000_init_eeprom_params(struct e1000_hw *hw) eeprom->opcode_bits = 3; eeprom->address_bits = 6; eeprom->delay_usec = 50; - eeprom->use_eerd = FALSE; - eeprom->use_eewr = FALSE; + eeprom->use_eerd = false; + eeprom->use_eewr = false; break; case e1000_82540: case e1000_82545: @@ -439,8 +439,8 @@ static int32_t e1000_init_eeprom_params(struct e1000_hw *hw) eeprom->word_size = 64; eeprom->address_bits = 6; } - eeprom->use_eerd = FALSE; - eeprom->use_eewr = FALSE; + eeprom->use_eerd = false; + eeprom->use_eewr = false; break; case e1000_82541: case e1000_82541_rev_2: @@ -469,8 +469,8 @@ static int32_t e1000_init_eeprom_params(struct e1000_hw *hw) eeprom->address_bits = 6; } } - eeprom->use_eerd = FALSE; - eeprom->use_eewr = FALSE; + eeprom->use_eerd = false; + eeprom->use_eewr = false; break; case e1000_82571: case e1000_82572: @@ -484,8 +484,8 @@ static int32_t e1000_init_eeprom_params(struct e1000_hw *hw) eeprom->page_size = 8; eeprom->address_bits = 8; } - eeprom->use_eerd = FALSE; - eeprom->use_eewr = FALSE; + eeprom->use_eerd = false; + eeprom->use_eewr = false; break; case e1000_82573: case e1000_82574: @@ -499,9 +499,9 @@ static int32_t e1000_init_eeprom_params(struct e1000_hw *hw) eeprom->page_size = 8; eeprom->address_bits = 8; } - eeprom->use_eerd = TRUE; - eeprom->use_eewr = TRUE; - if (e1000_is_onboard_nvm_eeprom(hw) == FALSE) { + eeprom->use_eerd = true; + eeprom->use_eewr = true; + if (e1000_is_onboard_nvm_eeprom(hw) == false) { eeprom->type = e1000_eeprom_flash; eeprom->word_size = 2048; @@ -522,8 +522,8 @@ static int32_t e1000_init_eeprom_params(struct e1000_hw *hw) eeprom->page_size = 8; eeprom->address_bits = 8; } - eeprom->use_eerd = TRUE; - eeprom->use_eewr = FALSE; + eeprom->use_eerd = true; + eeprom->use_eewr = false; break; /* ich8lan does not support currently. if needed, please @@ -535,8 +535,8 @@ static int32_t e1000_init_eeprom_params(struct e1000_hw *hw) int32_t i = 0; eeprom->type = e1000_eeprom_ich8; - eeprom->use_eerd = FALSE; - eeprom->use_eewr = FALSE; + eeprom->use_eerd = false; + eeprom->use_eewr = false; eeprom->word_size = E1000_SHADOW_RAM_WORDS; uint32_t flash_size = E1000_READ_ICH_FLASH_REG(hw, ICH_FLASH_GFPREG); @@ -544,7 +544,7 @@ static int32_t e1000_init_eeprom_params(struct e1000_hw *hw) * so as to save time for driver init */ if (hw->eeprom_shadow_ram != NULL) { for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) { - hw->eeprom_shadow_ram[i].modified = FALSE; + hw->eeprom_shadow_ram[i].modified = false; hw->eeprom_shadow_ram[i].eeprom_word = 0xFFFF; } } @@ -779,8 +779,8 @@ e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset, * directly. In this case, we need to acquire the EEPROM so that * FW or other port software does not interrupt. */ - if (e1000_is_onboard_nvm_eeprom(hw) == TRUE && - hw->eeprom.use_eerd == FALSE) { + if (e1000_is_onboard_nvm_eeprom(hw) == true && + hw->eeprom.use_eerd == false) { /* Prepare the EEPROM for bit-bang reading */ if (e1000_acquire_eeprom(hw) != E1000_SUCCESS) @@ -788,7 +788,7 @@ e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset, } /* Eerd register EEPROM access requires no eeprom aquire/release */ - if (eeprom->use_eerd == TRUE) + if (eeprom->use_eerd == true) return e1000_read_eeprom_eerd(hw, offset, words, data); /* ich8lan does not support currently. if needed, please @@ -935,7 +935,7 @@ e1000_set_phy_mode(struct e1000_hw *hw) if (ret_val) return ret_val; - hw->phy_reset_disable = FALSE; + hw->phy_reset_disable = false; } } @@ -1098,17 +1098,17 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask) return E1000_SUCCESS; } -static boolean_t e1000_is_second_port(struct e1000_hw *hw) +static bool e1000_is_second_port(struct e1000_hw *hw) { switch (hw->mac_type) { case e1000_80003es2lan: case e1000_82546: case e1000_82571: if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) - return TRUE; + return true; /* Fallthrough */ default: - return FALSE; + return false; } } @@ -1373,7 +1373,7 @@ e1000_reset_hw(struct e1000_hw *hw) E1000_WRITE_FLUSH(hw); /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */ - hw->tbi_compatibility_on = FALSE; + hw->tbi_compatibility_on = false; /* Delay to allow any outstanding PCI transactions to complete before * resetting the device @@ -2098,7 +2098,7 @@ e1000_copper_link_preconfig(struct e1000_hw *hw) hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 || hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2) - hw->phy_reset_disable = FALSE; + hw->phy_reset_disable = false; return E1000_SUCCESS; } @@ -2118,7 +2118,7 @@ e1000_copper_link_preconfig(struct e1000_hw *hw) ****************************************************************************/ static int32_t -e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active) +e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active) { uint32_t phy_ctrl = 0; int32_t ret_val; @@ -2253,7 +2253,7 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active) ****************************************************************************/ static int32_t -e1000_set_d0_lplu_state(struct e1000_hw *hw, boolean_t active) +e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active) { uint32_t phy_ctrl = 0; int32_t ret_val; @@ -2378,7 +2378,7 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw) /* The NVM settings will configure LPLU in D3 for IGP2 and IGP3 PHYs */ if (hw->phy_type == e1000_phy_igp) { /* disable lplu d3 during driver init */ - ret_val = e1000_set_d3_lplu_state(hw, FALSE); + ret_val = e1000_set_d3_lplu_state(hw, false); if (ret_val) { DEBUGOUT("Error Disabling LPLU D3\n"); return ret_val; @@ -2386,7 +2386,7 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw) } /* disable lplu d0 during driver init */ - ret_val = e1000_set_d0_lplu_state(hw, FALSE); + ret_val = e1000_set_d0_lplu_state(hw, false); if (ret_val) { DEBUGOUT("Error Disabling LPLU D0\n"); return ret_val; @@ -2495,9 +2495,9 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw) /***************************************************************************** * This function checks the mode of the firmware. * - * returns - TRUE when the mode is IAMT or FALSE. + * returns - true when the mode is IAMT or false. ****************************************************************************/ -boolean_t +bool e1000_check_mng_mode(struct e1000_hw *hw) { uint32_t fwsm; @@ -2508,12 +2508,12 @@ e1000_check_mng_mode(struct e1000_hw *hw) if (hw->mac_type == e1000_ich8lan) { if ((fwsm & E1000_FWSM_MODE_MASK) == (E1000_MNG_ICH_IAMT_MODE << E1000_FWSM_MODE_SHIFT)) - return TRUE; + return true; } else if ((fwsm & E1000_FWSM_MODE_MASK) == (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)) - return TRUE; + return true; - return FALSE; + return false; } static int32_t @@ -2675,7 +2675,7 @@ e1000_copper_link_ggp_setup(struct e1000_hw *hw) * firmware will have already initialized them. We only initialize * them if the HW is not in IAMT mode. */ - if (e1000_check_mng_mode(hw) == FALSE) { + if (e1000_check_mng_mode(hw) == false) { /* Enable Electrical Idle on the PHY */ phy_data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE; ret_val = e1000_write_phy_reg(hw, @@ -2879,7 +2879,7 @@ e1000_copper_link_autoneg(struct e1000_hw *hw) } } - hw->get_link_status = TRUE; + hw->get_link_status = true; return E1000_SUCCESS; } @@ -3598,7 +3598,7 @@ e1000_check_for_link(struct eth_device *nic) } if (phy_data & MII_SR_LINK_STATUS) { - hw->get_link_status = FALSE; + hw->get_link_status = false; } else { /* No link detected */ return -E1000_ERR_NOLINK; @@ -3661,7 +3661,7 @@ e1000_check_for_link(struct eth_device *nic) rctl = E1000_READ_REG(hw, RCTL); rctl &= ~E1000_RCTL_SBP; E1000_WRITE_REG(hw, RCTL, rctl); - hw->tbi_compatibility_on = FALSE; + hw->tbi_compatibility_on = false; } } else { /* If TBI compatibility is was previously off, turn it on. For @@ -3670,7 +3670,7 @@ e1000_check_for_link(struct eth_device *nic) * will look like CRC errors to to the hardware. */ if (!hw->tbi_compatibility_on) { - hw->tbi_compatibility_on = TRUE; + hw->tbi_compatibility_on = true; rctl = E1000_READ_REG(hw, RCTL); rctl |= E1000_RCTL_SBP; E1000_WRITE_REG(hw, RCTL, rctl); @@ -4569,7 +4569,7 @@ e1000_detect_gig_phy(struct e1000_hw *hw) { int32_t phy_init_status, ret_val; uint16_t phy_id_high, phy_id_low; - boolean_t match = FALSE; + bool match = false; DEBUGFUNC(); @@ -4609,11 +4609,11 @@ e1000_detect_gig_phy(struct e1000_hw *hw) switch (hw->mac_type) { case e1000_82543: if (hw->phy_id == M88E1000_E_PHY_ID) - match = TRUE; + match = true; break; case e1000_82544: if (hw->phy_id == M88E1000_I_PHY_ID) - match = TRUE; + match = true; break; case e1000_82540: case e1000_82545: @@ -4621,37 +4621,37 @@ e1000_detect_gig_phy(struct e1000_hw *hw) case e1000_82546: case e1000_82546_rev_3: if (hw->phy_id == M88E1011_I_PHY_ID) - match = TRUE; + match = true; break; case e1000_82541: case e1000_82541_rev_2: case e1000_82547: case e1000_82547_rev_2: if(hw->phy_id == IGP01E1000_I_PHY_ID) - match = TRUE; + match = true; break; case e1000_82573: if (hw->phy_id == M88E1111_I_PHY_ID) - match = TRUE; + match = true; break; case e1000_82574: if (hw->phy_id == BME1000_E_PHY_ID) - match = TRUE; + match = true; break; case e1000_80003es2lan: if (hw->phy_id == GG82563_E_PHY_ID) - match = TRUE; + match = true; break; case e1000_ich8lan: if (hw->phy_id == IGP03E1000_E_PHY_ID) - match = TRUE; + match = true; if (hw->phy_id == IFE_E_PHY_ID) - match = TRUE; + match = true; if (hw->phy_id == IFE_PLUS_E_PHY_ID) - match = TRUE; + match = true; if (hw->phy_id == IFE_C_E_PHY_ID) - match = TRUE; + match = true; break; default: DEBUGOUT("Invalid MAC type %d\n", hw->mac_type); @@ -4682,7 +4682,7 @@ e1000_set_media_type(struct e1000_hw *hw) if (hw->mac_type != e1000_82543) { /* tbi_compatibility is only valid on 82543 */ - hw->tbi_compatibility_en = FALSE; + hw->tbi_compatibility_en = false; } switch (hw->device_id) { @@ -4714,7 +4714,7 @@ e1000_set_media_type(struct e1000_hw *hw) if (status & E1000_STATUS_TBIMODE) { hw->media_type = e1000_media_type_fiber; /* tbi_compatibility not valid on fiber */ - hw->tbi_compatibility_en = FALSE; + hw->tbi_compatibility_en = false; } else { hw->media_type = e1000_media_type_copper; } @@ -4788,8 +4788,8 @@ e1000_sw_init(struct eth_device *nic) hw->media_type = e1000_media_type_fiber; } - hw->tbi_compatibility_en = TRUE; - hw->wait_autoneg_complete = TRUE; + hw->tbi_compatibility_en = true; + hw->wait_autoneg_complete = true; if (hw->mac_type < e1000_82543) hw->report_tx_early = 0; else @@ -5194,7 +5194,7 @@ e1000_initialize(bd_t * bis) hw->original_fc = e1000_fc_default; hw->autoneg_failed = 0; hw->autoneg = 1; - hw->get_link_status = TRUE; + hw->get_link_status = true; hw->hw_addr = pci_map_bar(devno, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); hw->mac_type = e1000_undefined; diff --git a/drivers/net/e1000.h b/drivers/net/e1000.h index 1bbae50..6b93c2b 100644 --- a/drivers/net/e1000.h +++ b/drivers/net/e1000.h @@ -89,11 +89,6 @@ int do_e1000_spi(cmd_tbl_t *cmdtp, struct e1000_hw *hw, int argc, char * const argv[]); #endif -typedef enum { - FALSE = 0, - TRUE = 1 -} boolean_t; - /* Enumerated types specific to the e1000 hardware */ /* Media Access Controlers */ typedef enum { @@ -340,7 +335,7 @@ struct e1000_phy_stats { Control and Address */ #define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY special control register */ -#define IFE_PHY_RCV_FALSE_CARRIER 0x13 /* 100BaseTx Receive False +#define IFE_PHY_RCV_FALSE_CARRIER 0x13 /* 100BaseTx Receive false Carrier Counter */ #define IFE_PHY_RCV_DISCONNECT 0x14 /* 100BaseTx Receive Disconnet Counter */ @@ -1040,14 +1035,14 @@ struct e1000_hw_stats { }; struct e1000_eeprom_info { - e1000_eeprom_type type; - uint16_t word_size; - uint16_t opcode_bits; - uint16_t address_bits; - uint16_t delay_usec; - uint16_t page_size; - boolean_t use_eerd; - boolean_t use_eewr; +e1000_eeprom_type type; + uint16_t word_size; + uint16_t opcode_bits; + uint16_t address_bits; + uint16_t delay_usec; + uint16_t page_size; + bool use_eerd; + bool use_eewr; }; typedef enum { @@ -1150,20 +1145,20 @@ struct e1000_hw { #if 0 uint8_t perm_mac_addr[NODE_ADDRESS_SIZE]; #endif - boolean_t disable_polarity_correction; - boolean_t speed_downgraded; - boolean_t get_link_status; - boolean_t tbi_compatibility_en; - boolean_t tbi_compatibility_on; - boolean_t fc_strict_ieee; - boolean_t fc_send_xon; - boolean_t report_tx_early; - boolean_t phy_reset_disable; - boolean_t initialize_hw_bits_disable; + bool disable_polarity_correction; + bool speed_downgraded; + bool get_link_status; + bool tbi_compatibility_en; + bool tbi_compatibility_on; + bool fc_strict_ieee; + bool fc_send_xon; + bool report_tx_early; + bool phy_reset_disable; + bool initialize_hw_bits_disable; #if 0 - boolean_t adaptive_ifs; - boolean_t ifs_params_forced; - boolean_t in_ifs_mode; + bool adaptive_ifs; + bool ifs_params_forced; + bool in_ifs_mode; #endif e1000_smart_speed smart_speed; e1000_dsp_config dsp_config_state; @@ -1860,11 +1855,11 @@ struct e1000_hw { * Typical use: * ... * if (TBI_ACCEPT) { - * accept_frame = TRUE; + * accept_frame = true; * e1000_tbi_adjust_stats(adapter, MacAddress); * frame_length--; * } else { - * accept_frame = FALSE; + * accept_frame = false; * } * ... */ @@ -2080,7 +2075,7 @@ struct e1000_hw { #define GG82563_PSSR2_ENERGY_DETECT_CHANGED 0x0010 /* 1=Energy Detect Changed */ #define GG82563_PSSR2_DOWNSHIFT_INTERRUPT 0x0020 /* 1=Downshift Detected */ #define GG82563_PSSR2_MDI_CROSSOVER_CHANGE 0x0040 /* 1=Crossover Changed */ -#define GG82563_PSSR2_FALSE_CARRIER 0x0100 /* 1=False Carrier */ +#define GG82563_PSSR2_FALSE_CARRIER 0x0100 /* 1=false Carrier */ #define GG82563_PSSR2_SYMBOL_ERROR 0x0200 /* 1=Symbol Error */ #define GG82563_PSSR2_LINK_STATUS_CHANGED 0x0400 /* 1=Link Status Changed */ #define GG82563_PSSR2_AUTO_NEG_COMPLETED 0x0800 /* 1=Auto-Neg Completed */ diff --git a/drivers/net/e1000_spi.c b/drivers/net/e1000_spi.c index 5f774f4..93043a1 100644 --- a/drivers/net/e1000_spi.c +++ b/drivers/net/e1000_spi.c @@ -17,7 +17,7 @@ * never return an error. */ static int e1000_spi_xfer(struct e1000_hw *hw, unsigned int bitlen, - const void *dout_mem, void *din_mem, boolean_t intr) + const void *dout_mem, void *din_mem, bool intr) { const uint8_t *dout = dout_mem; uint8_t *din = din_mem; @@ -145,7 +145,7 @@ int spi_xfer(struct spi_slave *spi, unsigned int bitlen, if (flags & SPI_XFER_BEGIN) e1000_standby_eeprom(hw); - ret = e1000_spi_xfer(hw, bitlen, dout_mem, din_mem, TRUE); + ret = e1000_spi_xfer(hw, bitlen, dout_mem, din_mem, true); if (flags & SPI_XFER_END) e1000_standby_eeprom(hw); @@ -169,7 +169,7 @@ int spi_xfer(struct spi_slave *spi, unsigned int bitlen, #define SPI_EEPROM_STATUS_BUSY 0x01 #define SPI_EEPROM_STATUS_WREN 0x02 -static int e1000_spi_eeprom_enable_wr(struct e1000_hw *hw, boolean_t intr) +static int e1000_spi_eeprom_enable_wr(struct e1000_hw *hw, bool intr) { u8 op[] = { SPI_EEPROM_ENABLE_WR }; e1000_standby_eeprom(hw); @@ -181,7 +181,7 @@ static int e1000_spi_eeprom_enable_wr(struct e1000_hw *hw, boolean_t intr) * of the EEPROM commands at this time. */ #if 0 -static int e1000_spi_eeprom_disable_wr(struct e1000_hw *hw, boolean_t intr) +static int e1000_spi_eeprom_disable_wr(struct e1000_hw *hw, bool intr) { u8 op[] = { SPI_EEPROM_DISABLE_WR }; e1000_standby_eeprom(hw); @@ -189,7 +189,7 @@ static int e1000_spi_eeprom_disable_wr(struct e1000_hw *hw, boolean_t intr) } static int e1000_spi_eeprom_write_status(struct e1000_hw *hw, - u8 status, boolean_t intr) + u8 status, bool intr) { u8 op[] = { SPI_EEPROM_WRITE_STATUS, status }; e1000_standby_eeprom(hw); @@ -197,7 +197,7 @@ static int e1000_spi_eeprom_write_status(struct e1000_hw *hw, } #endif -static int e1000_spi_eeprom_read_status(struct e1000_hw *hw, boolean_t intr) +static int e1000_spi_eeprom_read_status(struct e1000_hw *hw, bool intr) { u8 op[] = { SPI_EEPROM_READ_STATUS, 0 }; e1000_standby_eeprom(hw); @@ -207,7 +207,7 @@ static int e1000_spi_eeprom_read_status(struct e1000_hw *hw, boolean_t intr) } static int e1000_spi_eeprom_write_page(struct e1000_hw *hw, - const void *data, u16 off, u16 len, boolean_t intr) + const void *data, u16 off, u16 len, bool intr) { u8 op[] = { SPI_EEPROM_WRITE_PAGE, @@ -225,7 +225,7 @@ static int e1000_spi_eeprom_write_page(struct e1000_hw *hw, } static int e1000_spi_eeprom_read_page(struct e1000_hw *hw, - void *data, u16 off, u16 len, boolean_t intr) + void *data, u16 off, u16 len, bool intr) { u8 op[] = { SPI_EEPROM_READ_PAGE, @@ -242,7 +242,7 @@ static int e1000_spi_eeprom_read_page(struct e1000_hw *hw, return 0; } -static int e1000_spi_eeprom_poll_ready(struct e1000_hw *hw, boolean_t intr) +static int e1000_spi_eeprom_poll_ready(struct e1000_hw *hw, bool intr) { int status; while ((status = e1000_spi_eeprom_read_status(hw, intr)) >= 0) { @@ -253,7 +253,7 @@ static int e1000_spi_eeprom_poll_ready(struct e1000_hw *hw, boolean_t intr) } static int e1000_spi_eeprom_dump(struct e1000_hw *hw, - void *data, u16 off, unsigned int len, boolean_t intr) + void *data, u16 off, unsigned int len, bool intr) { /* Interruptibly wait for the EEPROM to be ready */ if (e1000_spi_eeprom_poll_ready(hw, intr)) @@ -282,7 +282,7 @@ static int e1000_spi_eeprom_dump(struct e1000_hw *hw, } static int e1000_spi_eeprom_program(struct e1000_hw *hw, - const void *data, u16 off, u16 len, boolean_t intr) + const void *data, u16 off, u16 len, bool intr) { /* Program each page in sequence */ while (len) { @@ -362,7 +362,7 @@ static int do_e1000_spi_show(cmd_tbl_t *cmdtp, struct e1000_hw *hw, free(buffer); return 1; } - err = e1000_spi_eeprom_dump(hw, buffer, offset, length, TRUE); + err = e1000_spi_eeprom_dump(hw, buffer, offset, length, true); e1000_release_eeprom(hw); if (err) { E1000_ERR(hw->nic, "Interrupted!\n"); @@ -421,7 +421,7 @@ static int do_e1000_spi_dump(cmd_tbl_t *cmdtp, struct e1000_hw *hw, } /* Perform the programming operation */ - if (e1000_spi_eeprom_dump(hw, dest, offset, length, TRUE) < 0) { + if (e1000_spi_eeprom_dump(hw, dest, offset, length, true) < 0) { E1000_ERR(hw->nic, "Interrupted!\n"); e1000_release_eeprom(hw); return 1; @@ -456,7 +456,7 @@ static int do_e1000_spi_program(cmd_tbl_t *cmdtp, struct e1000_hw *hw, } /* Perform the programming operation */ - if (e1000_spi_eeprom_program(hw, source, offset, length, TRUE) < 0) { + if (e1000_spi_eeprom_program(hw, source, offset, length, true) < 0) { E1000_ERR(hw->nic, "Interrupted!\n"); e1000_release_eeprom(hw); return 1; @@ -472,7 +472,7 @@ static int do_e1000_spi_checksum(cmd_tbl_t *cmdtp, struct e1000_hw *hw, { uint16_t i, length, checksum = 0, checksum_reg; uint16_t *buffer; - boolean_t upd; + bool upd; if (argc == 0) upd = 0; @@ -498,7 +498,7 @@ static int do_e1000_spi_checksum(cmd_tbl_t *cmdtp, struct e1000_hw *hw, } /* Read the EEPROM */ - if (e1000_spi_eeprom_dump(hw, buffer, 0, length, TRUE) < 0) { + if (e1000_spi_eeprom_dump(hw, buffer, 0, length, true) < 0) { E1000_ERR(hw->nic, "Interrupted!\n"); e1000_release_eeprom(hw); return 1; @@ -533,7 +533,7 @@ static int do_e1000_spi_checksum(cmd_tbl_t *cmdtp, struct e1000_hw *hw, printf("%s: Reprogramming the EEPROM checksum...\n", hw->nic->name); buffer[i] = cpu_to_le16(checksum); if (e1000_spi_eeprom_program(hw, &buffer[i], i * sizeof(uint16_t), - sizeof(uint16_t), TRUE)) { + sizeof(uint16_t), true)) { E1000_ERR(hw->nic, "Interrupted!\n"); e1000_release_eeprom(hw); return 1; diff --git a/drivers/net/ne2000_base.h b/drivers/net/ne2000_base.h index 5446de4..eee0956 100644 --- a/drivers/net/ne2000_base.h +++ b/drivers/net/ne2000_base.h @@ -79,10 +79,6 @@ are GPL, so this is, of course, GPL. #ifndef __NE2000_BASE_H__ #define __NE2000_BASE_H__ -#define bool int -#define false 0 -#define true 1 - /* * Debugging details * diff --git a/drivers/net/npe/IxEthAcc.c b/drivers/net/npe/IxEthAcc.c index 20d3d9e..7185558 100644 --- a/drivers/net/npe/IxEthAcc.c +++ b/drivers/net/npe/IxEthAcc.c @@ -82,7 +82,7 @@ extern PUBLIC IxOsalMutex ixEthAccControlInterfaceMutex; * @ingroup IxEthAccPri * */ -BOOL ixEthAccServiceInit = FALSE; +BOOL ixEthAccServiceInit = false; /* global filtering bit mask */ PUBLIC UINT32 ixEthAccNewSrcMask; @@ -168,7 +168,7 @@ PUBLIC IxEthAccStatus ixEthAccInit() } /* initialiasation is complete */ - ixEthAccServiceInit = TRUE; + ixEthAccServiceInit = true; return IX_ETH_ACC_SUCCESS; @@ -200,11 +200,11 @@ PUBLIC void ixEthAccUnload(void) /* set all ports as uninitialized */ for (portId = 0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++) { - ixEthAccPortData[portId].portInitialized = FALSE; + ixEthAccPortData[portId].portInitialized = false; } /* uninitialize the service */ - ixEthAccServiceInit = FALSE; + ixEthAccServiceInit = false; } } @@ -248,7 +248,7 @@ PUBLIC IxEthAccStatus ixEthAccPortInit( IxEthAccPortId portId) * Set the port init flag. */ - ixEthAccPortData[portId].portInitialized = TRUE; + ixEthAccPortData[portId].portInitialized = true; #ifdef CONFIG_IXP425_COMPONENT_ETHDB /* init learning/filtering database structures for this port */ diff --git a/drivers/net/npe/IxEthAccCommon.c b/drivers/net/npe/IxEthAccCommon.c index 211203d..b93a8c8 100644 --- a/drivers/net/npe/IxEthAccCommon.c +++ b/drivers/net/npe/IxEthAccCommon.c @@ -102,7 +102,7 @@ IxEthAccQregInfo ixEthAccQmgrRxDefaultTemplate = (IxQMgrCallbackId) 0, /**< Callback tag */ IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */ IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */ - TRUE, /**< Enable Q notification at startup */ + true, /**< Enable Q notification at startup */ IX_ETH_ACC_RX_FRAME_ETH_Q_SOURCE,/**< Q Condition to drive callback */ IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ IX_QMGR_Q_WM_LEVEL1, /**< Q High water mark - needed by NPE */ @@ -122,7 +122,7 @@ IxEthAccQregInfo ixEthAccQmgrRxSmallTemplate = (IxQMgrCallbackId) 0, /**< Callback tag */ IX_QMGR_Q_SIZE64, /**< Allocate Smaller Q */ IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */ - TRUE, /**< Enable Q notification at startup */ + true, /**< Enable Q notification at startup */ IX_ETH_ACC_RX_FRAME_ETH_Q_SOURCE,/**< Q Condition to drive callback */ IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ IX_QMGR_Q_WM_LEVEL1, /**< Q High water mark - needed by NPE */ @@ -144,7 +144,7 @@ IxEthAccQregInfo ixEthAccQmgrStaticInfo[]= (IxQMgrCallbackId) IX_ETH_PORT_1, IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */ IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */ - FALSE, /**< Disable Q notification at startup */ + false, /**< Disable Q notification at startup */ IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q_SOURCE, /**< Q Condition to drive callback */ IX_QMGR_Q_WM_LEVEL0, /***< Q Low water mark */ IX_QMGR_Q_WM_LEVEL64, /**< Q High water mark */ @@ -157,7 +157,7 @@ IxEthAccQregInfo ixEthAccQmgrStaticInfo[]= (IxQMgrCallbackId) IX_ETH_PORT_2, IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */ IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */ - FALSE, /**< Disable Q notification at startup */ + false, /**< Disable Q notification at startup */ IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q_SOURCE, /**< Q Condition to drive callback */ IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ IX_QMGR_Q_WM_LEVEL64, /**< Q High water mark */ @@ -170,7 +170,7 @@ IxEthAccQregInfo ixEthAccQmgrStaticInfo[]= (IxQMgrCallbackId) IX_ETH_PORT_3, IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */ IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */ - FALSE, /**< Disable Q notification at startup */ + false, /**< Disable Q notification at startup */ IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q_SOURCE, /**< Q Condition to drive callback */ IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ IX_QMGR_Q_WM_LEVEL64, /**< Q High water mark */ @@ -183,7 +183,7 @@ IxEthAccQregInfo ixEthAccQmgrStaticInfo[]= (IxQMgrCallbackId) IX_ETH_PORT_1, IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */ IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */ - FALSE, /**< Disable Q notification at startup */ + false, /**< Disable Q notification at startup */ IX_ETH_ACC_TX_FRAME_ENET0_Q_SOURCE, /**< Q Condition to drive callback */ IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ IX_QMGR_Q_WM_LEVEL64, /**< Q High water mark */ @@ -196,7 +196,7 @@ IxEthAccQregInfo ixEthAccQmgrStaticInfo[]= (IxQMgrCallbackId) IX_ETH_PORT_2, IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */ IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */ - FALSE, /**< Disable Q notification at startup */ + false, /**< Disable Q notification at startup */ IX_ETH_ACC_TX_FRAME_ENET1_Q_SOURCE, /**< Q Condition to drive callback */ IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ IX_QMGR_Q_WM_LEVEL64, /**< Q High water mark */ @@ -209,7 +209,7 @@ IxEthAccQregInfo ixEthAccQmgrStaticInfo[]= (IxQMgrCallbackId) IX_ETH_PORT_3, IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */ IX_QMGR_Q_ENTRY_SIZE1, /** Queue Entry Sizes - all Q entries are single ord entries */ - FALSE, /** Disable Q notification at startup */ + false, /** Disable Q notification at startup */ IX_ETH_ACC_TX_FRAME_ENET2_Q_SOURCE, /** Q Condition to drive callback */ IX_QMGR_Q_WM_LEVEL0, /* No queues use almost empty */ IX_QMGR_Q_WM_LEVEL64, /** Q High water mark - needed used */ @@ -222,7 +222,7 @@ IxEthAccQregInfo ixEthAccQmgrStaticInfo[]= (IxQMgrCallbackId) 0, IX_QMGR_Q_SIZE128, /**< Allocate Max Size Q */ IX_QMGR_Q_ENTRY_SIZE1, /**< Queue Entry Sizes - all Q entries are single word entries */ - TRUE, /**< Enable Q notification at startup */ + true, /**< Enable Q notification at startup */ IX_ETH_ACC_TX_FRAME_DONE_ETH_Q_SOURCE, /**< Q Condition to drive callback */ IX_QMGR_Q_WM_LEVEL0, /**< Q Low water mark */ IX_QMGR_Q_WM_LEVEL2, /**< Q High water mark - needed by NPE */ @@ -449,7 +449,7 @@ ixEthAccQMgrQueueSetup(IxEthAccQregInfo *qInfoDes) /* * Set notification condition for Q */ - if ( qInfoDes->qNotificationEnableAtStartup == TRUE ) + if (qInfoDes->qNotificationEnableAtStartup == true) { if ( ixQMgrNotificationEnable(qInfoDes->qId, qInfoDes->qConditionSource) @@ -513,7 +513,7 @@ IxEthAccStatus ixEthAccQMgrQueuesConfig(void) IxEthDBProperty ixEthDBTrafficClass = IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY; IxEthDBPropertyType ixEthDBPropertyType = IX_ETH_DB_INTEGER_PROPERTY; UINT32 ixEthDBParameter = 0; - BOOL completelySorted = FALSE; + BOOL completelySorted = false; /* Fill the corspondance between ports and queues * This defines the mapping from port to queue Ids. @@ -706,7 +706,7 @@ IxEthAccStatus ixEthAccQMgrQueuesConfig(void) do { sortIterations++; - completelySorted = TRUE; + completelySorted = true; for (rxQueue = 0; rxQueue < rxQueueCount - sortIterations; rxQueue++) @@ -732,7 +732,7 @@ IxEthAccStatus ixEthAccQMgrQueuesConfig(void) rxQueues[rxQueue+1].npeId = npeId; rxQueues[rxQueue+1].qId = qId; rxQueues[rxQueue+1].trafficClass = trafficClass; - completelySorted = FALSE; + completelySorted = false; } } } diff --git a/drivers/net/npe/IxEthAccDataPlane.c b/drivers/net/npe/IxEthAccDataPlane.c index b62f0d0..6df3307 100644 --- a/drivers/net/npe/IxEthAccDataPlane.c +++ b/drivers/net/npe/IxEthAccDataPlane.c @@ -948,7 +948,7 @@ IxEthAccStatus ixEthAccPortRxCallbackRegister(IxEthAccPortId portId, for (port = 0; port < IX_ETH_ACC_NUMBER_OF_PORTS; port++) { if ((ixEthAccMacState[port].portDisableState == ACTIVE) - && (ixEthAccPortData[port].ixEthAccRxData.rxMultiBufferCallbackInUse == TRUE)) + && (ixEthAccPortData[port].ixEthAccRxData.rxMultiBufferCallbackInUse == true)) { /* one of the active ports has a different rx callback type. * Changing the callback type when the port is enabled @@ -977,7 +977,7 @@ IxEthAccStatus ixEthAccPortRxCallbackRegister(IxEthAccPortId portId, return (IX_ETH_ACC_INVALID_ARG); } - ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackInUse = FALSE; + ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackInUse = false; return (IX_ETH_ACC_SUCCESS); } @@ -1025,7 +1025,7 @@ IxEthAccStatus ixEthAccPortMultiBufferRxCallbackRegister( for (port = 0; port < IX_ETH_ACC_NUMBER_OF_PORTS; port++) { if ((ixEthAccMacState[port].portDisableState == ACTIVE) - && (ixEthAccPortData[port].ixEthAccRxData.rxMultiBufferCallbackInUse == FALSE)) + && (ixEthAccPortData[port].ixEthAccRxData.rxMultiBufferCallbackInUse == false)) { /* one of the active ports has a different rx callback type. * Changing the callback type when the port is enabled @@ -1055,7 +1055,7 @@ IxEthAccStatus ixEthAccPortMultiBufferRxCallbackRegister( return (IX_ETH_ACC_INVALID_ARG); } - ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackInUse = TRUE; + ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackInUse = true; return (IX_ETH_ACC_SUCCESS); } @@ -1456,7 +1456,7 @@ ixEthRxFrameProcess(IxEthAccPortId portId, IX_OSAL_MBUF *mbufPtr) IX_ETH_ACC_FATAL_LOG( "ixEthRxFrameProcess: Illegal port: %u\n", (UINT32)portId, 0, 0, 0, 0, 0); - return FALSE; + return false; } #endif @@ -1468,7 +1468,7 @@ ixEthRxFrameProcess(IxEthAccPortId portId, IX_OSAL_MBUF *mbufPtr) if ((flags & (IX_ETHACC_NE_FILTERMASK | IX_ETHACC_NE_NEWSRCMASK)) == 0) { /* "best case" scenario : nothing special to do for this frame */ - return TRUE; + return true; } #ifdef CONFIG_IXP425_COMPONENT_ETHDB @@ -1540,10 +1540,10 @@ ixEthRxFrameProcess(IxEthAccPortId portId, IX_OSAL_MBUF *mbufPtr) RX_STATS_INC(portId, rxFiltered); /* indicate that frame should not be subjected to further processing */ - return FALSE; + return false; } - return TRUE; + return true; } diff --git a/drivers/net/npe/IxEthAccMac.c b/drivers/net/npe/IxEthAccMac.c index 369ee91..5540b33 100644 --- a/drivers/net/npe/IxEthAccMac.c +++ b/drivers/net/npe/IxEthAccMac.c @@ -304,7 +304,7 @@ ixEthAccPortEnablePriv(IxEthAccPortId portId) /* set the global state */ ixEthAccMacState[portId].portDisableState = ACTIVE; - ixEthAccMacState[portId].enabled = TRUE; + ixEthAccMacState[portId].enabled = true; /* rewrite the setup (including mac filtering) depending * on current options @@ -515,7 +515,7 @@ ixEthAccPortDisableRxCallback (UINT32 cbTag, IxEthAccPortId portId = (IxEthAccPortId)cbTag; /* call the portDisable receive callback */ - (ixEthAccPortDisableRxTable[portId])(portId, mBufPtr, FALSE); + (ixEthAccPortDisableRxTable[portId])(portId, mBufPtr, false); } PRIVATE void @@ -527,7 +527,7 @@ ixEthAccPortDisableMultiBufferRxCallback (UINT32 cbTag, while (*mBufPtr) { /* call the portDisable receive callback with one buffer at a time */ - (ixEthAccPortDisableRxTable[portId])(portId, *mBufPtr++, TRUE); + (ixEthAccPortDisableRxTable[portId])(portId, *mBufPtr++, true); } } @@ -820,7 +820,7 @@ ixEthAccPortDisablePriv(IxEthAccPortId portId) } /* disable MAC Tx and Rx services */ - ixEthAccMacState[portId].enabled = FALSE; + ixEthAccMacState[portId].enabled = false; ixEthAccMacStateUpdate(portId); /* restore the Rx and TxDone callbacks (within a critical section) */ @@ -869,14 +869,14 @@ ixEthAccPortEnabledQueryPriv(IxEthAccPortId portId, BOOL *enabled) IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot enable port.\n",(INT32)portId,0,0,0,0,0); /* Since Eth NPE is not available, port must be disabled */ - *enabled = FALSE ; + *enabled = false ; return IX_ETH_ACC_SUCCESS ; } if (!IX_ETH_IS_PORT_INITIALIZED(portId)) { /* Since Eth NPE is not available, port must be disabled */ - *enabled = FALSE ; + *enabled = false ; return (IX_ETH_ACC_PORT_UNINITIALIZED); } @@ -1259,7 +1259,7 @@ ixEthAccPortPromiscuousModeClearPriv(IxEthAccPortId portId) IX_ETH_ACC_MAC_RX_CNTRL1, regval | IX_ETH_ACC_RX_CNTRL1_ADDR_FLTR_EN); - ixEthAccMacState[portId].promiscuous = FALSE; + ixEthAccMacState[portId].promiscuous = false; ixEthAccMulticastAddressSet(portId); @@ -1297,7 +1297,7 @@ ixEthAccPortPromiscuousModeSetPriv(IxEthAccPortId portId) IX_ETH_ACC_MAC_RX_CNTRL1, regval | IX_ETH_ACC_RX_CNTRL1_ADDR_FLTR_EN); - ixEthAccMacState[portId].promiscuous = TRUE; + ixEthAccMacState[portId].promiscuous = true; ixEthAccMulticastAddressSet(portId); @@ -1361,7 +1361,7 @@ ixEthAccPortUnicastMacAddressSetPriv (IxEthAccPortId portId, IX_ETH_ACC_MAC_UNI_ADDR_1 + i*sizeof(UINT32), macAddr->macAddress[i]); } - ixEthAccMacState[portId].initDone = TRUE; + ixEthAccMacState[portId].initDone = true; return IX_ETH_ACC_SUCCESS; } @@ -1552,7 +1552,7 @@ ixEthAccPortMulticastAddressJoinAllPriv (IxEthAccPortId portId) IX_IEEE803_MAC_ADDRESS_SIZE); ixEthAccMacState[portId].mcastAddrIndex = 1; - ixEthAccMacState[portId].joinAll = TRUE; + ixEthAccMacState[portId].joinAll = true; ixEthAccMulticastAddressSet(portId); @@ -1599,7 +1599,7 @@ ixEthAccPortMulticastAddressLeavePriv (IxEthAccPortId portId, { if(ixEthAccMacEqual(macAddr, &mcastMacAddr)) { - ixEthAccMacState[portId].joinAll = FALSE; + ixEthAccMacState[portId].joinAll = false; } /*Decrement the index into the multicast address table for the current port*/ @@ -1643,7 +1643,7 @@ ixEthAccPortMulticastAddressLeaveAllPriv (IxEthAccPortId portId) } ixEthAccMacState[portId].mcastAddrIndex = 0; - ixEthAccMacState[portId].joinAll = FALSE; + ixEthAccMacState[portId].joinAll = false; ixEthAccMulticastAddressSet(portId); @@ -1770,7 +1770,7 @@ ixEthAccPortDuplexModeSetPriv (IxEthAccPortId portId, REG_WRITE(ixEthAccMacBase[portId], IX_ETH_ACC_MAC_RX_CNTRL1, rxregval | IX_ETH_ACC_RX_CNTRL1_PAUSE_EN); - ixEthAccMacState[portId].fullDuplex = TRUE; + ixEthAccMacState[portId].fullDuplex = true; } else if (mode == IX_ETH_ACC_HALF_DUPLEX) @@ -1786,7 +1786,7 @@ ixEthAccPortDuplexModeSetPriv (IxEthAccPortId portId, IX_ETH_ACC_MAC_RX_CNTRL1, rxregval & ~IX_ETH_ACC_RX_CNTRL1_PAUSE_EN); - ixEthAccMacState[portId].fullDuplex = FALSE; + ixEthAccMacState[portId].fullDuplex = false; } else { @@ -1876,7 +1876,7 @@ ixEthAccPortTxFrameAppendPaddingEnablePriv (IxEthAccPortId portId) regval | IX_ETH_ACC_TX_CNTRL1_PAD_EN); - ixEthAccMacState[portId].txPADAppend = TRUE; + ixEthAccMacState[portId].txPADAppend = true; return IX_ETH_ACC_SUCCESS; } @@ -1908,7 +1908,7 @@ ixEthAccPortTxFrameAppendPaddingDisablePriv (IxEthAccPortId portId) IX_ETH_ACC_MAC_TX_CNTRL1, regval & ~IX_ETH_ACC_TX_CNTRL1_PAD_EN); - ixEthAccMacState[portId].txPADAppend = FALSE; + ixEthAccMacState[portId].txPADAppend = false; return IX_ETH_ACC_SUCCESS; } @@ -1941,7 +1941,7 @@ ixEthAccPortTxFrameAppendFCSEnablePriv (IxEthAccPortId portId) IX_ETH_ACC_MAC_TX_CNTRL1, regval | IX_ETH_ACC_TX_CNTRL1_FCS_EN); - ixEthAccMacState[portId].txFCSAppend = TRUE; + ixEthAccMacState[portId].txFCSAppend = true; return IX_ETH_ACC_SUCCESS; } @@ -1973,7 +1973,7 @@ ixEthAccPortTxFrameAppendFCSDisablePriv (IxEthAccPortId portId) IX_ETH_ACC_MAC_TX_CNTRL1, regval & ~IX_ETH_ACC_TX_CNTRL1_FCS_EN); - ixEthAccMacState[portId].txFCSAppend = FALSE; + ixEthAccMacState[portId].txFCSAppend = false; return IX_ETH_ACC_SUCCESS; } @@ -2004,7 +2004,7 @@ ixEthAccPortRxFrameAppendFCSEnablePriv (IxEthAccPortId portId) IX_ETH_ACC_MAC_RX_CNTRL1, regval | IX_ETH_ACC_RX_CNTRL1_CRC_EN); - ixEthAccMacState[portId].rxFCSAppend = TRUE; + ixEthAccMacState[portId].rxFCSAppend = true; return IX_ETH_ACC_SUCCESS; } @@ -2035,7 +2035,7 @@ ixEthAccPortRxFrameAppendFCSDisablePriv (IxEthAccPortId portId) IX_ETH_ACC_MAC_RX_CNTRL1, regval & ~IX_ETH_ACC_RX_CNTRL1_CRC_EN); - ixEthAccMacState[portId].rxFCSAppend = FALSE; + ixEthAccMacState[portId].rxFCSAppend = false; return IX_ETH_ACC_SUCCESS; } @@ -2327,17 +2327,17 @@ ixEthAccMacInit(IxEthAccPortId portId) return IX_ETH_ACC_SUCCESS ; } - if(ixEthAccMacState[portId].macInitialised == FALSE) + if(ixEthAccMacState[portId].macInitialised == false) { - ixEthAccMacState[portId].fullDuplex = TRUE; - ixEthAccMacState[portId].rxFCSAppend = TRUE; - ixEthAccMacState[portId].txFCSAppend = TRUE; - ixEthAccMacState[portId].txPADAppend = TRUE; - ixEthAccMacState[portId].enabled = FALSE; - ixEthAccMacState[portId].promiscuous = TRUE; - ixEthAccMacState[portId].joinAll = FALSE; - ixEthAccMacState[portId].initDone = FALSE; - ixEthAccMacState[portId].macInitialised = TRUE; + ixEthAccMacState[portId].fullDuplex = true; + ixEthAccMacState[portId].rxFCSAppend = true; + ixEthAccMacState[portId].txFCSAppend = true; + ixEthAccMacState[portId].txPADAppend = true; + ixEthAccMacState[portId].enabled = false; + ixEthAccMacState[portId].promiscuous = true; + ixEthAccMacState[portId].joinAll = false; + ixEthAccMacState[portId].initDone = false; + ixEthAccMacState[portId].macInitialised = true; /* initialize MIB stats mutexes */ ixOsalMutexInit(&ixEthAccMacState[portId].ackMIBStatsLock); @@ -2417,7 +2417,7 @@ ixEthAccMacStateUpdate(IxEthAccPortId portId) { UINT32 regval; - if ( ixEthAccMacState[portId].enabled == FALSE ) + if ( ixEthAccMacState[portId].enabled == false ) { /* Just disable both the transmitter and reciver in the MAC. */ REG_READ(ixEthAccMacBase[portId], @@ -2480,7 +2480,7 @@ ixEthAccMacStateUpdate(IxEthAccPortId portId) ixEthAccPortPromiscuousModeClearPriv(portId); } - if ( ixEthAccMacState[portId].enabled == TRUE ) + if ( ixEthAccMacState[portId].enabled == true ) { /* Enable both the transmitter and reciver in the MAC. */ REG_READ(ixEthAccMacBase[portId], @@ -2509,10 +2509,10 @@ ixEthAccMacEqual(IxEthAccMacAddr *macAddr1, { if(macAddr1->macAddress[i] != macAddr2->macAddress[i]) { - return FALSE; + return false; } } - return TRUE; + return true; } PRIVATE void @@ -2554,7 +2554,7 @@ ixEthAccMulticastAddressSet(IxEthAccPortId portId) * are set in the result */ - if (ixEthAccMacState[portId].promiscuous == TRUE) + if (ixEthAccMacState[portId].promiscuous == true) { /* Promiscuous Mode is set, and filtering * allow all packets, and enable the mcast and @@ -2569,7 +2569,7 @@ ixEthAccMulticastAddressSet(IxEthAccPortId portId) } else { - if(ixEthAccMacState[portId].joinAll == TRUE) + if(ixEthAccMacState[portId].joinAll == true) { /* Join all is set. The mask and address are * the multicast settings. diff --git a/drivers/net/npe/IxEthDBAPI.c b/drivers/net/npe/IxEthDBAPI.c index b2bfb72..d46c47c 100644 --- a/drivers/net/npe/IxEthDBAPI.c +++ b/drivers/net/npe/IxEthDBAPI.c @@ -60,7 +60,7 @@ IxEthDBStatus ixEthDBFilteringStaticEntryProvision(IxEthDBPortId portID, IxEthDB IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING); - return ixEthDBTriggerAddPortUpdate(macAddr, portID, TRUE); + return ixEthDBTriggerAddPortUpdate(macAddr, portID, true); } IX_ETH_DB_PUBLIC @@ -74,7 +74,7 @@ IxEthDBStatus ixEthDBFilteringDynamicEntryProvision(IxEthDBPortId portID, IxEthD IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING); - return ixEthDBTriggerAddPortUpdate(macAddr, portID, FALSE); + return ixEthDBTriggerAddPortUpdate(macAddr, portID, false); } IX_ETH_DB_PUBLIC @@ -102,7 +102,7 @@ void ixEthDBDatabaseMaintenance() { HashIterator iterator; UINT32 portIndex; - BOOL agingRequired = FALSE; + BOOL agingRequired = false; /* ports who will have deleted records and therefore will need updating */ IxEthDBPortMap triggerPorts; @@ -120,7 +120,7 @@ void ixEthDBDatabaseMaintenance() { if (ixEthDBPortInfo[portIndex].agingEnabled && ixEthDBPortInfo[portIndex].enabled) { - agingRequired = TRUE; + agingRequired = true; } } @@ -152,9 +152,9 @@ void ixEthDBDatabaseMaintenance() } else { - ixEthDBPortInfo[portIndex].agingEnabled = FALSE; - ixEthDBPortInfo[portIndex].updateMethod.updateEnabled = FALSE; - ixEthDBPortInfo[portIndex].updateMethod.userControlled = TRUE; + ixEthDBPortInfo[portIndex].agingEnabled = false; + ixEthDBPortInfo[portIndex].updateMethod.updateEnabled = false; + ixEthDBPortInfo[portIndex].updateMethod.userControlled = true; ixOsalLog(IX_OSAL_LOG_LVL_FATAL, IX_OSAL_LOG_DEV_STDOUT, @@ -173,7 +173,7 @@ void ixEthDBDatabaseMaintenance() { MacDescriptor *descriptor = (MacDescriptor *) iterator.node->data; UINT32 *age = NULL; - BOOL staticEntry = TRUE; + BOOL staticEntry = true; if (descriptor->type == IX_ETH_DB_FILTERING_RECORD) { @@ -187,10 +187,10 @@ void ixEthDBDatabaseMaintenance() } else { - staticEntry = TRUE; + staticEntry = true; } - if (ixEthDBPortInfo[descriptor->portID].agingEnabled && (staticEntry == FALSE)) + if (ixEthDBPortInfo[descriptor->portID].agingEnabled && (staticEntry == false)) { /* manually increment the age if the port has no such capability */ if ((ixEthDBPortDefinitions[descriptor->portID].capabilities & IX_ETH_ENTRY_AGING) == 0) @@ -341,7 +341,7 @@ IxEthDBStatus ixEthDBPortAgingDisable(IxEthDBPortId portID) IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING); - ixEthDBPortInfo[portID].agingEnabled = FALSE; + ixEthDBPortInfo[portID].agingEnabled = false; return IX_ETH_DB_SUCCESS; } @@ -355,7 +355,7 @@ IxEthDBStatus ixEthDBPortAgingEnable(IxEthDBPortId portID) IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_LEARNING); - ixEthDBPortInfo[portID].agingEnabled = TRUE; + ixEthDBPortInfo[portID].agingEnabled = true; return IX_ETH_DB_SUCCESS; } @@ -442,7 +442,7 @@ IxEthDBStatus ixEthDBPortUpdateEnableSet(IxEthDBPortId portID, BOOL enableUpdate IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_FILTERING); ixEthDBPortInfo[portID].updateMethod.updateEnabled = enableUpdate; - ixEthDBPortInfo[portID].updateMethod.userControlled = TRUE; + ixEthDBPortInfo[portID].updateMethod.userControlled = true; return IX_ETH_DB_SUCCESS; } diff --git a/drivers/net/npe/IxEthDBAPISupport.c b/drivers/net/npe/IxEthDBAPISupport.c index 36bc200..1facb89 100644 --- a/drivers/net/npe/IxEthDBAPISupport.c +++ b/drivers/net/npe/IxEthDBAPISupport.c @@ -128,18 +128,18 @@ void ixEthDBPortInit(IxEthDBPortId portID) SET_DEPENDENCY_MAP(portInfo->dependencyPortMap, portID); /* default values */ - portInfo->agingEnabled = FALSE; - portInfo->enabled = FALSE; - portInfo->macAddressUploaded = FALSE; + portInfo->agingEnabled = false; + portInfo->enabled = false; + portInfo->macAddressUploaded = false; portInfo->maxRxFrameSize = IX_ETHDB_DEFAULT_FRAME_SIZE; portInfo->maxTxFrameSize = IX_ETHDB_DEFAULT_FRAME_SIZE; /* default update control values */ portInfo->updateMethod.searchTree = NULL; - portInfo->updateMethod.searchTreePendingWrite = FALSE; - portInfo->updateMethod.treeInitialized = FALSE; - portInfo->updateMethod.updateEnabled = FALSE; - portInfo->updateMethod.userControlled = FALSE; + portInfo->updateMethod.searchTreePendingWrite = false; + portInfo->updateMethod.treeInitialized = false; + portInfo->updateMethod.updateEnabled = false; + portInfo->updateMethod.userControlled = false; /* default WiFi parameters */ memset(portInfo->bbsid, 0, sizeof (portInfo->bbsid)); @@ -153,9 +153,9 @@ void ixEthDBPortInit(IxEthDBPortId portID) } /* initialize state save */ - ixEthDBPortState[portID].saved = FALSE; + ixEthDBPortState[portID].saved = false; - portInfo->initialized = TRUE; + portInfo->initialized = true; } /** @@ -190,7 +190,7 @@ IxEthDBStatus ixEthDBPortEnable(IxEthDBPortId portID) SET_DEPENDENCY_MAP(triggerPorts, portID); /* mark as enabled */ - portInfo->enabled = TRUE; + portInfo->enabled = true; /* Operation stops here when Ethernet Learning is not enabled */ if(IX_FEATURE_CTRL_SWCONFIG_DISABLED == @@ -214,7 +214,7 @@ IxEthDBStatus ixEthDBPortEnable(IxEthDBPortId portID) if (!portInfo->updateMethod.userControlled && ((portInfo->featureCapability & IX_ETH_DB_FILTERING) != 0)) { - portInfo->updateMethod.updateEnabled = TRUE; + portInfo->updateMethod.updateEnabled = true; } /* if this is first time initialization then we already have @@ -227,7 +227,7 @@ IxEthDBStatus ixEthDBPortEnable(IxEthDBPortId portID) ixEthDBUpdatePortLearningTrees(triggerPorts); /* mark tree as being initialized */ - portInfo->updateMethod.treeInitialized = TRUE; + portInfo->updateMethod.treeInitialized = true; } } @@ -262,7 +262,7 @@ IxEthDBStatus ixEthDBPortEnable(IxEthDBPortId portID) ixEthDBFilteringPortMaximumTxFrameSizeSet(portID, ixEthDBPortState[portID].maxTxFrameSize); /* discard previous save */ - ixEthDBPortState[portID].saved = FALSE; + ixEthDBPortState[portID].saved = false; } IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Enabling succeeded for port %d\n", portID); @@ -321,7 +321,7 @@ IxEthDBStatus ixEthDBPortDisable(IxEthDBPortId portID) memcpy(ixEthDBPortState[portID].transmitTaggingInfo, portInfo->transmitTaggingInfo, sizeof (IxEthDBVlanSet)); memcpy(ixEthDBPortState[portID].priorityTable, portInfo->priorityTable, sizeof (IxEthDBPriorityTable)); - ixEthDBPortState[portID].saved = TRUE; + ixEthDBPortState[portID].saved = true; /* now turn off all EthDB filtering features on the port */ @@ -330,7 +330,7 @@ IxEthDBStatus ixEthDBPortDisable(IxEthDBPortId portID) if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0) { ixEthDBPortVlanMembershipRangeAdd((IxEthDBPortId) portID, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID); - ixEthDBEgressVlanRangeTaggingEnabledSet((IxEthDBPortId) portID, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID, FALSE); + ixEthDBEgressVlanRangeTaggingEnabledSet((IxEthDBPortId) portID, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID, false); ixEthDBAcceptableFrameTypeSet((IxEthDBPortId) portID, IX_ETH_DB_ACCEPT_ALL_FRAMES); ixEthDBIngressVlanTaggingEnabledSet((IxEthDBPortId) portID, IX_ETH_DB_PASS_THROUGH); @@ -342,7 +342,7 @@ IxEthDBStatus ixEthDBPortDisable(IxEthDBPortId portID) /* STP */ if ((portInfo->featureCapability & IX_ETH_DB_SPANNING_TREE_PROTOCOL) != 0) { - ixEthDBSpanningTreeBlockingStateSet((IxEthDBPortId) portID, FALSE); + ixEthDBSpanningTreeBlockingStateSet((IxEthDBPortId) portID, false); } /* Firewall */ @@ -350,7 +350,7 @@ IxEthDBStatus ixEthDBPortDisable(IxEthDBPortId portID) { ixEthDBFirewallModeSet((IxEthDBPortId) portID, IX_ETH_DB_FIREWALL_BLACK_LIST); ixEthDBFirewallTableDownload((IxEthDBPortId) portID); - ixEthDBFirewallInvalidAddressFilterEnable((IxEthDBPortId) portID, FALSE); + ixEthDBFirewallInvalidAddressFilterEnable((IxEthDBPortId) portID, false); } /* Frame size filter */ @@ -413,18 +413,18 @@ IxEthDBStatus ixEthDBPortDisable(IxEthDBPortId portID) } /* mark as disabled */ - portInfo->enabled = FALSE; + portInfo->enabled = false; /* disable updates unless the user has specifically altered the default behavior */ if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE) { if (!portInfo->updateMethod.userControlled) { - portInfo->updateMethod.updateEnabled = FALSE; + portInfo->updateMethod.updateEnabled = false; } /* make sure we re-initialize the NPE learning tree when the port is re-enabled */ - portInfo->updateMethod.treeInitialized = FALSE; + portInfo->updateMethod.treeInitialized = false; } ixEthDBUpdateUnlock(); @@ -668,7 +668,7 @@ IxEthDBStatus ixEthDBPortAddressSet(IxEthDBPortId portID, IxEthDBMacAddr *macAdd if (result == IX_SUCCESS) { - ixEthDBPortInfo[portID].macAddressUploaded = TRUE; + ixEthDBPortInfo[portID].macAddressUploaded = true; } return result; diff --git a/drivers/net/npe/IxEthDBCore.c b/drivers/net/npe/IxEthDBCore.c index 25b7cbb..8b3c1d9 100644 --- a/drivers/net/npe/IxEthDBCore.c +++ b/drivers/net/npe/IxEthDBCore.c @@ -51,7 +51,7 @@ IX_ETH_DB_PUBLIC BOOL ixEthDBPortUpdateRequired[IX_ETH_DB_MAX_RECORD_TYPE_INDEX IX_ETH_DB_PUBLIC UINT32 ixEthDBKeyType[IX_ETH_DB_MAX_RECORD_TYPE_INDEX + 1]; /* private initialization flag */ -IX_ETH_DB_PRIVATE BOOL ethDBInitializationComplete = FALSE; +IX_ETH_DB_PRIVATE BOOL ethDBInitializationComplete = false; /** * @brief initializes EthDB @@ -124,7 +124,7 @@ IxEthDBStatus ixEthDBInit(void) ixEthDBFeatureCapabilityScan(); } - ethDBInitializationComplete = TRUE; + ethDBInitializationComplete = true; return result; } @@ -179,7 +179,7 @@ IxEthDBStatus ixEthDBUnload(void) ixOsalMutexDestroy(&ixEthDBPortInfo[portIndex].npeAckLock); } - ixEthDBPortInfo[portIndex].initialized = FALSE; + ixEthDBPortInfo[portIndex].initialized = false; } /* shutdown event processor */ @@ -188,7 +188,7 @@ IxEthDBStatus ixEthDBUnload(void) /* deallocate NPE update zones */ ixEthDBNPEUpdateAreasUnload(); - ethDBInitializationComplete = FALSE; + ethDBInitializationComplete = false; return IX_ETH_DB_SUCCESS; } diff --git a/drivers/net/npe/IxEthDBEvents.c b/drivers/net/npe/IxEthDBEvents.c index 4d44e03..529063d 100644 --- a/drivers/net/npe/IxEthDBEvents.c +++ b/drivers/net/npe/IxEthDBEvents.c @@ -61,8 +61,8 @@ IX_ETH_DB_PRIVATE PortEventQueue eventQueue; IX_ETH_DB_PRIVATE IxOsalMutex eventQueueLock; IX_ETH_DB_PRIVATE IxOsalMutex portUpdateLock; -IX_ETH_DB_PRIVATE BOOL ixEthDBLearningShutdown = FALSE; -IX_ETH_DB_PRIVATE BOOL ixEthDBEventProcessorRunning = FALSE; +IX_ETH_DB_PRIVATE BOOL ixEthDBLearningShutdown = false; +IX_ETH_DB_PRIVATE BOOL ixEthDBEventProcessorRunning = false; /* imported data */ extern HashTable dbHashtable; @@ -143,7 +143,7 @@ IxEthDBStatus ixEthDBStartLearningFunction(void) return IX_ETH_DB_FAIL; } - ixEthDBLearningShutdown = FALSE; + ixEthDBLearningShutdown = false; /* create processor loop thread */ if (ixOsalThreadCreate(&eventProcessorThread, &threadAttr, ixEthDBEventProcessorLoop, NULL) != IX_SUCCESS) @@ -173,7 +173,7 @@ IxEthDBStatus ixEthDBStartLearningFunction(void) IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBStopLearningFunction(void) { - ixEthDBLearningShutdown = TRUE; + ixEthDBLearningShutdown = true; /* wake up event processing loop to actually process the shutdown event */ ixOsalSemaphorePost(&eventQueueSemaphore); @@ -253,13 +253,13 @@ void ixEthDBEventProcessorLoop(void *unused1) IxEthDBPortMap triggerPorts; IxEthDBPortId portIndex; - ixEthDBEventProcessorRunning = TRUE; + ixEthDBEventProcessorRunning = true; IX_ETH_DB_EVENTS_TRACE("DB: (Events) Event processor loop was started\n"); while (!ixEthDBLearningShutdown) { - BOOL keepProcessing = TRUE; + BOOL keepProcessing = true; UINT32 processedEvents = 0; IX_ETH_DB_EVENTS_VERBOSE_TRACE("DB: (Events) Waiting for new learning event...\n"); @@ -302,7 +302,7 @@ void ixEthDBEventProcessorLoop(void *unused1) if (processedEvents > EVENT_PROCESSING_LIMIT /* maximum burst reached? */ || ixOsalSemaphoreTryWait(&eventQueueSemaphore) != IX_SUCCESS) /* or empty queue? */ { - keepProcessing = FALSE; + keepProcessing = false; } } @@ -313,10 +313,10 @@ void ixEthDBEventProcessorLoop(void *unused1) /* turn off automatic updates */ for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++) { - ixEthDBPortInfo[portIndex].updateMethod.updateEnabled = FALSE; + ixEthDBPortInfo[portIndex].updateMethod.updateEnabled = false; } - ixEthDBEventProcessorRunning = FALSE; + ixEthDBEventProcessorRunning = false; } /** @@ -381,7 +381,7 @@ void ixEthDBProcessEvent(PortEvent *local_event, IxEthDBPortMap triggerPorts) * * @param macAddr MAC address of the new record * @param portID port ID of the new record - * @param staticEntry TRUE if record is static, FALSE if dynamic + * @param staticEntry true if record is static, false if dynamic * * @return IX_ETH_DB_SUCCESS if the event creation was * successfull or IX_ETH_DB_BUSY if the event queue is full @@ -430,7 +430,7 @@ IxEthDBStatus ixEthDBTriggerRemovePortUpdate(IxEthDBMacAddr *macAddr, IxEthDBPor { if (ixEthDBPeek(macAddr, IX_ETH_DB_ALL_FILTERING_RECORDS) != IX_ETH_DB_NO_SUCH_ADDR) { - return ixEthDBTriggerPortUpdate(IX_ETH_DB_REMOVE_FILTERING_RECORD, macAddr, portID, FALSE); + return ixEthDBTriggerPortUpdate(IX_ETH_DB_REMOVE_FILTERING_RECORD, macAddr, portID, false); } else { diff --git a/drivers/net/npe/IxEthDBFeatures.c b/drivers/net/npe/IxEthDBFeatures.c index 7a58d26..c5b680a 100644 --- a/drivers/net/npe/IxEthDBFeatures.c +++ b/drivers/net/npe/IxEthDBFeatures.c @@ -169,7 +169,7 @@ void ixEthDBFeatureCapabilityScan(void) /* enable port, VLAN and Firewall feature bits to initialize QoS/VLAN/Firewall configuration */ portInfo->featureStatus |= IX_ETH_DB_VLAN_QOS; portInfo->featureStatus |= IX_ETH_DB_FIREWALL; - portInfo->enabled = TRUE; + portInfo->enabled = true; #define CONFIG_WITH_VLAN /* test-only: VLAN support not included to save space!!! */ #ifdef CONFIG_WITH_VLAN /* test-only: VLAN support not included to save space!!! */ @@ -195,7 +195,7 @@ void ixEthDBFeatureCapabilityScan(void) ixEthDBPortVlanMembershipRangeRemove(portIndex, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID); /* clear TTI table - no VLAN tagged frames will be transmitted */ - ixEthDBEgressVlanRangeTaggingEnabledSet(portIndex, 0, 4094, FALSE); + ixEthDBEgressVlanRangeTaggingEnabledSet(portIndex, 0, 4094, false); /* set membership on 0, otherwise no Tx or Rx is working */ ixEthDBPortVlanMembershipAdd(portIndex, 0); @@ -221,12 +221,12 @@ void ixEthDBFeatureCapabilityScan(void) #endif /* by default we turn off invalid source MAC address filtering */ - ixEthDBFirewallInvalidAddressFilterEnable(portIndex, FALSE); + ixEthDBFirewallInvalidAddressFilterEnable(portIndex, false); /* disable port, VLAN, Firewall feature bits */ portInfo->featureStatus &= ~IX_ETH_DB_VLAN_QOS; portInfo->featureStatus &= ~IX_ETH_DB_FIREWALL; - portInfo->enabled = FALSE; + portInfo->enabled = false; /* enable filtering by default if present */ if ((portInfo->featureCapability & IX_ETH_DB_FILTERING) != 0) @@ -271,7 +271,7 @@ IxEthDBStatus ixEthDBFeatureCapabilityGet(IxEthDBPortId portID, IxEthDBFeature * * * @param portID ID of the port * @param feature feature to enable or disable - * @param enabled TRUE to enable the selected feature or FALSE to disable it + * @param enabled true to enable the selected feature or false to disable it * * Note that this function is documented in the main component * header file, IxEthDB.h. @@ -333,7 +333,7 @@ IxEthDBStatus ixEthDBFeatureEnable(IxEthDBPortId portID, IxEthDBFeature feature, } /* force port enabled */ - portInfo->enabled = TRUE; + portInfo->enabled = true; if (enable) { @@ -399,7 +399,7 @@ IxEthDBStatus ixEthDBFeatureEnable(IxEthDBPortId portID, IxEthDBFeature feature, /* enable TPID port extraction */ if (status == IX_ETH_DB_SUCCESS) { - status = ixEthDBVlanPortExtractionEnable(portID, TRUE); + status = ixEthDBVlanPortExtractionEnable(portID, true); } } else if (feature == IX_ETH_DB_FIREWALL) @@ -414,7 +414,7 @@ IxEthDBStatus ixEthDBFeatureEnable(IxEthDBPortId portID, IxEthDBFeature feature, if (status == IX_ETH_DB_SUCCESS) { - status = ixEthDBFirewallInvalidAddressFilterEnable(portID, FALSE); + status = ixEthDBFirewallInvalidAddressFilterEnable(portID, false); } } } @@ -445,7 +445,7 @@ IxEthDBStatus ixEthDBFeatureEnable(IxEthDBPortId portID, IxEthDBFeature feature, if (status == IX_ETH_DB_SUCCESS) { - status = ixEthDBFirewallInvalidAddressFilterEnable(portID, FALSE); + status = ixEthDBFirewallInvalidAddressFilterEnable(portID, false); } if (status == IX_ETH_DB_SUCCESS) @@ -515,7 +515,7 @@ IxEthDBStatus ixEthDBFeatureEnable(IxEthDBPortId portID, IxEthDBFeature feature, /* disable TPID port extraction */ if (status == IX_ETH_DB_SUCCESS) { - status = ixEthDBVlanPortExtractionEnable(portID, FALSE); + status = ixEthDBVlanPortExtractionEnable(portID, false); } } #endif @@ -538,9 +538,9 @@ IxEthDBStatus ixEthDBFeatureEnable(IxEthDBPortId portID, IxEthDBFeature feature, * * @param portID port ID * @param present location to store a boolean value indicating - * if the feature is present (TRUE) or not (FALSE) + * if the feature is present (true) or not (false) * @param enabled location to store a booleam value indicating - * if the feature is present (TRUE) or not (FALSE) + * if the feature is present (true) or not (false) * * Note that this function is documented in the main component * header file, IxEthDB.h. diff --git a/drivers/net/npe/IxEthDBFirewall.c b/drivers/net/npe/IxEthDBFirewall.c index eb46174..6fb5ab6 100644 --- a/drivers/net/npe/IxEthDBFirewall.c +++ b/drivers/net/npe/IxEthDBFirewall.c @@ -72,7 +72,7 @@ IxEthDBStatus ixEthDBFirewallUpdate(IxEthDBPortId portID, void *address, UINT32 UINT32 mode = 0; PortInfo *portInfo = &ixEthDBPortInfo[portID]; - mode = (portInfo->srcAddressFilterEnabled != FALSE) << 1 | (portInfo->firewallMode == IX_ETH_DB_FIREWALL_WHITE_LIST); + mode = (portInfo->srcAddressFilterEnabled != false) << 1 | (portInfo->firewallMode == IX_ETH_DB_FIREWALL_WHITE_LIST); FILL_SETFIREWALLMODE_MSG(message, IX_ETH_DB_PORT_ID_TO_NPE_LOGICAL_ID(portID), @@ -123,8 +123,8 @@ IxEthDBStatus ixEthDBFirewallModeSet(IxEthDBPortId portID, IxEthDBFirewallMode m * @brief enables or disables the invalid source MAC address filter * * @param portID ID of the port - * @param enable TRUE to enable invalid source MAC address filtering - * or FALSE to disable it + * @param enable true to enable invalid source MAC address filtering + * or false to disable it * * The invalid source MAC address filter will discard, when enabled, * frames whose source MAC address is a multicast or the broadcast MAC diff --git a/drivers/net/npe/IxEthDBLearning.c b/drivers/net/npe/IxEthDBLearning.c index 2287dbe..8406741 100644 --- a/drivers/net/npe/IxEthDBLearning.c +++ b/drivers/net/npe/IxEthDBLearning.c @@ -105,8 +105,8 @@ UINT32 ixEthDBKeyXORHash(void *key) * collisions, i.e. descriptors with different mac addresses and the same * hash value, where this function is used to differentiate entries. * - * @retval TRUE if the entry matches the reference key (equal addresses) - * @retval FALSE if the entry does not match the reference key + * @retval true if the entry matches the reference key (equal addresses) + * @retval false if the entry does not match the reference key * * @internal */ diff --git a/drivers/net/npe/IxEthDBNPEAdaptor.c b/drivers/net/npe/IxEthDBNPEAdaptor.c index 112a46c..d47ffec 100644 --- a/drivers/net/npe/IxEthDBNPEAdaptor.c +++ b/drivers/net/npe/IxEthDBNPEAdaptor.c @@ -203,7 +203,7 @@ void ixEthDBNPESyncScan(IxEthDBPortId portID, void *eltBaseAddress, UINT32 eltSi /* debug */ IX_ETH_DB_NPE_VERBOSE_TRACE("DB: (NPEAdaptor) checking node at offset %d...\n", eltEntryOffset / ELT_ENTRY_SIZE); - if (IX_EDB_NPE_NODE_VALID(eltNodeAddress) != TRUE) + if (IX_EDB_NPE_NODE_VALID(eltNodeAddress) != true) { IX_ETH_DB_NPE_VERBOSE_TRACE("\t... node is empty\n"); } diff --git a/drivers/net/npe/IxEthDBPortUpdate.c b/drivers/net/npe/IxEthDBPortUpdate.c index cdf114b..813e4ee 100644 --- a/drivers/net/npe/IxEthDBPortUpdate.c +++ b/drivers/net/npe/IxEthDBPortUpdate.c @@ -60,7 +60,7 @@ extern HashTable dbHashtable; * * @param typeArray array indexed on record types, each * element indicating whether the record type requires an - * automatic update (TRUE) or not (FALSE) + * automatic update (true) or not (false) * * Automatic updates are done for registered record types * upon adding, updating (that is, updating the record portID) @@ -70,7 +70,7 @@ extern HashTable dbHashtable; * * It is assumed that the typeArray parameter is allocated large * enough to hold all the user defined types. Also, the type - * array should be initialized to FALSE as this function only + * array should be initialized to false as this function only * caters for types which do require automatic updates. * * Note that this function should be called by the component @@ -84,8 +84,8 @@ extern HashTable dbHashtable; IX_ETH_DB_PUBLIC UINT32 ixEthDBUpdateTypeRegister(BOOL *typeArray) { - typeArray[IX_ETH_DB_FILTERING_RECORD] = TRUE; - typeArray[IX_ETH_DB_FILTERING_VLAN_RECORD] = TRUE; + typeArray[IX_ETH_DB_FILTERING_RECORD] = true; + typeArray[IX_ETH_DB_FILTERING_VLAN_RECORD] = true; return 2; } @@ -174,7 +174,7 @@ void ixEthDBCreateTrees(IxEthDBPortMap updatePorts) { UINT32 portIndex; BOOL result; - BOOL portsLeft = TRUE; + BOOL portsLeft = true; while (portsLeft) { @@ -305,11 +305,11 @@ void ixEthDBCreateTrees(IxEthDBPortMap updatePorts) } /* mark tree as valid */ - port->updateMethod.searchTreePendingWrite = TRUE; + port->updateMethod.searchTreePendingWrite = true; } else { - portsLeft = FALSE; + portsLeft = false; IX_ETH_DB_UPDATE_TRACE("DB: (Update) No trees to create this round\n"); } @@ -374,7 +374,7 @@ IxEthDBStatus ixEthDBNPEUpdateHandler(IxEthDBPortId portID, IxEthDBRecordType ty /* forget last used search tree */ port->updateMethod.searchTree = NULL; - port->updateMethod.searchTreePendingWrite = FALSE; + port->updateMethod.searchTreePendingWrite = false; /* dependending on the update type we do different things */ if (type == IX_ETH_DB_FILTERING_RECORD || type == IX_ETH_DB_WIFI_RECORD) @@ -393,9 +393,9 @@ IxEthDBStatus ixEthDBNPEUpdateHandler(IxEthDBPortId portID, IxEthDBRecordType ty } else { - ixEthDBPortInfo[portID].agingEnabled = FALSE; - ixEthDBPortInfo[portID].updateMethod.updateEnabled = FALSE; - ixEthDBPortInfo[portID].updateMethod.userControlled = TRUE; + ixEthDBPortInfo[portID].agingEnabled = false; + ixEthDBPortInfo[portID].updateMethod.updateEnabled = false; + ixEthDBPortInfo[portID].updateMethod.userControlled = true; ERROR_LOG("EthDB: (PortUpdate) disabling aging and updates on port %d (assumed dead)\n", portID); diff --git a/drivers/net/npe/IxEthDBReports.c b/drivers/net/npe/IxEthDBReports.c index 9c7ae1c..912e608 100644 --- a/drivers/net/npe/IxEthDBReports.c +++ b/drivers/net/npe/IxEthDBReports.c @@ -62,7 +62,7 @@ IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBDependencyPortMapShow(IxEthDBPortId portID, IxEthDBPortMap map) { UINT32 portIndex; - BOOL mapSelf = TRUE, mapNone = TRUE, firstPort = TRUE; + BOOL mapSelf = true, mapNone = true, firstPort = true; /* dependency port maps */ printf("Dependency port map: "); @@ -72,22 +72,22 @@ IxEthDBStatus ixEthDBDependencyPortMapShow(IxEthDBPortId portID, IxEthDBPortMap { if (IS_PORT_INCLUDED(portIndex, map)) { - mapNone = FALSE; + mapNone = false; if (portIndex != portID) { - mapSelf = FALSE; + mapSelf = false; } printf("%s%d", firstPort ? "{" : ", ", portIndex); - firstPort = FALSE; + firstPort = false; } } if (mapNone) { - mapSelf = FALSE; + mapSelf = false; } printf("%s (%s)\n", firstPort ? "" : "}", mapSelf ? "self" : mapNone ? "none" : "group"); diff --git a/drivers/net/npe/IxEthDBSearch.c b/drivers/net/npe/IxEthDBSearch.c index 4a10878..75fdebe 100644 --- a/drivers/net/npe/IxEthDBSearch.c +++ b/drivers/net/npe/IxEthDBSearch.c @@ -50,7 +50,7 @@ extern HashTable dbHashtable; * @param untypedReference record to match against * @param untypedEntry record to match * - * @return TRUE if the match is successful or FALSE otherwise + * @return true if the match is successful or false otherwise * * @internal */ @@ -61,7 +61,7 @@ BOOL ixEthDBAddressRecordMatch(void *untypedReference, void *untypedEntry) MacDescriptor *reference = (MacDescriptor *) untypedReference; /* check accepted record types */ - if ((entry->type & reference->type) == 0) return FALSE; + if ((entry->type & reference->type) == 0) return false; return (ixEthDBAddressCompare((UINT8 *) entry->macAddress, (UINT8 *) reference->macAddress) == 0); } @@ -73,7 +73,7 @@ BOOL ixEthDBAddressRecordMatch(void *untypedReference, void *untypedEntry) * @param untypedReference record to match against * @param untypedEntry record to match * - * @return TRUE if the match is successful or FALSE otherwise + * @return true if the match is successful or false otherwise * * @internal */ @@ -84,7 +84,7 @@ BOOL ixEthDBVlanRecordMatch(void *untypedReference, void *untypedEntry) MacDescriptor *reference = (MacDescriptor *) untypedReference; /* check accepted record types */ - if ((entry->type & reference->type) == 0) return FALSE; + if ((entry->type & reference->type) == 0) return false; return (IX_ETH_DB_GET_VLAN_ID(entry->recordData.filteringVlanData.ieee802_1qTag) == IX_ETH_DB_GET_VLAN_ID(reference->recordData.filteringVlanData.ieee802_1qTag)) && @@ -98,7 +98,7 @@ BOOL ixEthDBVlanRecordMatch(void *untypedReference, void *untypedEntry) * @param untypedReference record to match against * @param untypedEntry record to match * - * @return TRUE if the match is successful or FALSE otherwise + * @return true if the match is successful or false otherwise * * @internal */ @@ -109,7 +109,7 @@ BOOL ixEthDBPortRecordMatch(void *untypedReference, void *untypedEntry) MacDescriptor *reference = (MacDescriptor *) untypedReference; /* check accepted record types */ - if ((entry->type & reference->type) == 0) return FALSE; + if ((entry->type & reference->type) == 0) return false; return (entry->portID == reference->portID) && (ixEthDBAddressCompare(entry->macAddress, reference->macAddress) == 0); @@ -125,7 +125,7 @@ BOOL ixEthDBPortRecordMatch(void *untypedReference, void *untypedEntry) * array on invalid types. Calling it will display an * error message, indicating an error in the component logic. * - * @return FALSE + * @return false * * @internal */ @@ -137,7 +137,7 @@ BOOL ixEthDBNullMatch(void *reference, void *entry) ixOsalLog(IX_OSAL_LOG_LVL_WARNING, IX_OSAL_LOG_DEV_STDOUT, "DB: (Search) The NullMatch function was called, wrong key type?\n", 0, 0, 0, 0, 0, 0); - return FALSE; + return false; } /** diff --git a/drivers/net/npe/IxEthDBSpanningTree.c b/drivers/net/npe/IxEthDBSpanningTree.c index 6d9fd6e..029f7ac 100644 --- a/drivers/net/npe/IxEthDBSpanningTree.c +++ b/drivers/net/npe/IxEthDBSpanningTree.c @@ -49,7 +49,7 @@ * @brief sets the STP blocking state of a port * * @param portID ID of the port - * @param blocked TRUE to block the port or FALSE to unblock it + * @param blocked true to block the port or false to unblock it * * Note that this function is documented in the main component * header file, IxEthDB.h. diff --git a/drivers/net/npe/IxEthDBUtil.c b/drivers/net/npe/IxEthDBUtil.c index e708bf1..24acc24 100644 --- a/drivers/net/npe/IxEthDBUtil.c +++ b/drivers/net/npe/IxEthDBUtil.c @@ -94,13 +94,13 @@ BOOL ixEthDBCheckSingleBitValue(UINT32 value) while (value != 0) { - if (value == 1) return TRUE; - else if ((value & 1) == 1) return FALSE; + if (value == 1) return true; + else if ((value & 1) == 1) return false; value >>= 1; } - return FALSE; + return false; #endif } diff --git a/drivers/net/npe/IxEthDBVlan.c b/drivers/net/npe/IxEthDBVlan.c index e2efb9b..522a30b 100644 --- a/drivers/net/npe/IxEthDBVlan.c +++ b/drivers/net/npe/IxEthDBVlan.c @@ -642,7 +642,7 @@ IxEthDBStatus ixEthDBPortVlanMembershipGet(IxEthDBPortId portID, IxEthDBVlanSet * * @param portID ID of the port * @param vlanID VLAN ID to enable or disable Egress tagging on - * @param enabled TRUE to enable and FALSE to disable tagging + * @param enabled true to enable and false to disable tagging * * Note that this function is documented in the main component * header file, IxEthDB.h. @@ -670,7 +670,7 @@ IxEthDBStatus ixEthDBEgressVlanEntryTaggingEnabledSet(IxEthDBPortId portID, IxEt * @param portID ID of the port * @param vlanID VLAN ID to retrieve the tagging status for * @param enabled location to store the tagging status - * (TRUE - tagging enabled, FALSE - tagging disabled) + * (true - tagging enabled, false - tagging disabled) * * Note that this function is documented in the main component * header file, IxEthDB.h. @@ -702,7 +702,7 @@ IxEthDBStatus ixEthDBEgressVlanEntryTaggingEnabledGet(IxEthDBPortId portID, IxEt * @param portID ID of the port * @param vlanIDMin start of VLAN range * @param vlanIDMax end of VLAN range - * @param enabled TRUE to enable or FALSE to disable VLAN tagging + * @param enabled true to enable or false to disable VLAN tagging * * Note that this function is documented in the main component * header file, IxEthDB.h. @@ -1151,7 +1151,7 @@ IxEthDBStatus ixEthDBPriorityMappingClassGet(IxEthDBPortId portID, IxEthDBPriori * from the VLAN TPID field * * @param portID ID of the port - * @param enable TRUE to enable or FALSE to disable + * @param enable true to enable or false to disable * * Note that this function is documented in the main component * header file, IxEthDB.h. diff --git a/drivers/net/npe/IxEthMii.c b/drivers/net/npe/IxEthMii.c index 4d92f17..f8b439d 100644 --- a/drivers/net/npe/IxEthMii.c +++ b/drivers/net/npe/IxEthMii.c @@ -65,7 +65,7 @@ PRIVATE UINT32 ixEthMiiPhyId[IXP425_ETH_ACC_MII_MAX_ADDR]; * Scan for PHYs on the MII bus. This function returns * an array of booleans, one for each PHY address. * If a PHY is found at a particular address, the - * corresponding entry in the array is set to TRUE. + * corresponding entry in the array is set to true. * */ @@ -89,7 +89,7 @@ ixEthMiiPhyScan(BOOL phyPresent[], UINT32 maxPhyCount) i<IXP425_ETH_ACC_MII_MAX_ADDR; i++) { - phyPresent[i] = FALSE; + phyPresent[i] = false; } /* iterate through the PHY addresses */ @@ -119,7 +119,7 @@ ixEthMiiPhyScan(BOOL phyPresent[], UINT32 maxPhyCount) ) { /* supported phy */ - phyPresent[i] = TRUE; + phyPresent[i] = true; } /* end of if(ixEthMiiPhyId) */ else { @@ -131,7 +131,7 @@ ixEthMiiPhyScan(BOOL phyPresent[], UINT32 maxPhyCount) "ixEthMiiPhyScan : unexpected Mii PHY ID %8.8x\n", ixEthMiiPhyId[i], 2, 3, 4, 5, 6); ixEthMiiPhyId[i] = IX_ETH_MII_UNKNOWN_PHY_ID; - phyPresent[i] = TRUE; + phyPresent[i] = true; } } } @@ -347,10 +347,10 @@ ixEthMiiLinkStatus(UINT32 phyAddr, return IX_FAIL; } - *linkUp = FALSE; - *speed100 = FALSE; - *fullDuplex = FALSE; - *autoneg = FALSE; + *linkUp = false; + *speed100 = false; + *fullDuplex = false; + *autoneg = false; if ((phyAddr < IXP425_ETH_ACC_MII_MAX_ADDR) && (ixEthMiiPhyId[phyAddr] != IX_ETH_MII_INVALID_PHY_ID)) @@ -406,20 +406,20 @@ ixEthMiiLinkStatus(UINT32 phyAddr, if ((regval & IX_ETH_MII_SR_TX_FULL_DPX) != 0) { /* 100 Base X full dplx */ - *speed100 = TRUE; - *fullDuplex = TRUE; + *speed100 = true; + *fullDuplex = true; return IX_SUCCESS; } if ((regval & IX_ETH_MII_SR_TX_HALF_DPX) != 0) { /* 100 Base X half dplx */ - *speed100 = TRUE; + *speed100 = true; return IX_SUCCESS; } if ((regval & IX_ETH_MII_SR_10T_FULL_DPX) != 0) { /* 10 mb full dplx */ - *fullDuplex = TRUE; + *fullDuplex = true; return IX_SUCCESS; } if ((regval & IX_ETH_MII_SR_10T_HALF_DPX) != 0) diff --git a/drivers/net/npe/IxFeatureCtrl.c b/drivers/net/npe/IxFeatureCtrl.c index 2e196a1..b6728e4 100644 --- a/drivers/net/npe/IxFeatureCtrl.c +++ b/drivers/net/npe/IxFeatureCtrl.c @@ -72,7 +72,7 @@ IX_OSAL_WRITE_LONG(ixFeatureCtrlRegister, (value)); \ /* Boolean to mark the fact that the EXP_CONFIG address space was mapped */ -PRIVATE BOOL ixFeatureCtrlExpCfgRegionMapped = FALSE; +PRIVATE BOOL ixFeatureCtrlExpCfgRegionMapped = false; /* Pointer holding the virtual address of the Feature Control Register */ PRIVATE VUINT32 *ixFeatureCtrlRegister = NULL; @@ -81,7 +81,7 @@ PRIVATE VUINT32 *ixFeatureCtrlRegister = NULL; PRIVATE BOOL swConfiguration[IX_FEATURECTRL_SWCONFIG_MAX]; /* Flag to control swConfiguration[] is initialized once */ -PRIVATE BOOL swConfigurationFlag = FALSE ; +PRIVATE BOOL swConfigurationFlag = false ; /* Array containing component mask values */ #ifdef __ixp42X @@ -158,7 +158,7 @@ void ixFeatureCtrlExpMap(void) /* If the EXP Configuration space has already been mapped then * return */ - if (ixFeatureCtrlExpCfgRegionMapped == TRUE) + if (ixFeatureCtrlExpCfgRegionMapped == true) { return; } @@ -176,7 +176,7 @@ void ixFeatureCtrlExpMap(void) (VUINT32 *) (expCfgBaseAddress + IX_FEATURE_CTRL_REG_OFFSET); /* Mark the fact that the EXP_CONFIG space has already been mapped */ - ixFeatureCtrlExpCfgRegionMapped = TRUE; + ixFeatureCtrlExpCfgRegionMapped = true; } /** @@ -186,15 +186,15 @@ void ixFeatureCtrlExpMap(void) PRIVATE void ixFeatureCtrlSwConfigurationInit(void) { UINT32 i; - if (FALSE == swConfigurationFlag) + if (false == swConfigurationFlag) { for (i=0; i<IX_FEATURECTRL_SWCONFIG_MAX ; i++) { /* By default, all software configuration are enabled */ - swConfiguration[i]= TRUE ; + swConfiguration[i]= true ; } /*Make sure this function only initializes swConfiguration[] once*/ - swConfigurationFlag = TRUE ; + swConfigurationFlag = true ; } } @@ -326,7 +326,7 @@ ixFeatureCtrlProductIdRead () extern IxFeatureCtrlProductId AsmixFeatureCtrlProductIdRead(); #ifndef IN_KERNEL - mode = SetKMode(TRUE); + mode = SetKMode(true); #endif pdId = AsmixFeatureCtrlProductIdRead(); #ifndef IN_KERNEL @@ -372,7 +372,7 @@ ixFeatureCtrlSwConfigurationCheck (IxFeatureCtrlSwConfig swConfigType) ixFeatureCtrlSwConfigurationInit(); /* Check and return software configuration */ - return ((swConfiguration[(UINT32)swConfigType] == TRUE) ? IX_FEATURE_CTRL_SWCONFIG_ENABLED: IX_FEATURE_CTRL_SWCONFIG_DISABLED); + return ((swConfiguration[(UINT32)swConfigType] == true) ? IX_FEATURE_CTRL_SWCONFIG_ENABLED: IX_FEATURE_CTRL_SWCONFIG_DISABLED); } /** diff --git a/drivers/net/npe/IxNpeDl.c b/drivers/net/npe/IxNpeDl.c index 3738337..bfeac87 100644 --- a/drivers/net/npe/IxNpeDl.c +++ b/drivers/net/npe/IxNpeDl.c @@ -89,9 +89,9 @@ typedef struct */ static IxNpeDlNpeState ixNpeDlNpeState[IX_NPEDL_NPEID_MAX] = { - {FALSE, {IX_NPEDL_NPEID_MAX, 0, 0, 0}}, - {FALSE, {IX_NPEDL_NPEID_MAX, 0, 0, 0}}, - {FALSE, {IX_NPEDL_NPEID_MAX, 0, 0, 0}} + {false, {IX_NPEDL_NPEID_MAX, 0, 0, 0}}, + {false, {IX_NPEDL_NPEID_MAX, 0, 0, 0}}, + {false, {IX_NPEDL_NPEID_MAX, 0, 0, 0}} }; static IxNpeDlStats ixNpeDlStats; @@ -99,7 +99,7 @@ static IxNpeDlStats ixNpeDlStats; /* * Software guard to prevent NPE from being started multiple times. */ -static BOOL ixNpeDlNpeStarted[IX_NPEDL_NPEID_MAX] ={FALSE, FALSE, FALSE} ; +static BOOL ixNpeDlNpeStarted[IX_NPEDL_NPEID_MAX] ={false, false, false} ; /* @@ -195,7 +195,7 @@ ixNpeDlImageDownload (IxNpeDlImageId *imageIdPtr, if (IX_SUCCESS == status) { ixNpeDlNpeState[npeId].imageId = *imageIdPtr; - ixNpeDlNpeState[npeId].validImage = TRUE; + ixNpeDlNpeState[npeId].validImage = true; ixNpeDlStats.successfulDownloads++; status = ixNpeDlNpeExecutionStart (npeId); @@ -204,7 +204,7 @@ ixNpeDlImageDownload (IxNpeDlImageId *imageIdPtr, (status == IX_NPEDL_CRITICAL_MICROCODE_ERR)) { ixNpeDlNpeState[npeId].imageId = *imageIdPtr; - ixNpeDlNpeState[npeId].validImage = FALSE; + ixNpeDlNpeState[npeId].validImage = false; ixNpeDlStats.criticalFailDownloads++; } } /* end of if(IX_SUCCESS) */ /* condition: image located successfully in microcode image */ @@ -507,7 +507,7 @@ ixNpeDlNpeStopAndReset (IxNpeDlNpeId npeId) if (IX_SUCCESS == status) { /* Indicate NPE has been stopped */ - ixNpeDlNpeStarted[npeId] = FALSE ; + ixNpeDlNpeStarted[npeId] = false ; } return status; @@ -573,7 +573,7 @@ ixNpeDlNpeExecutionStart (IxNpeDlNpeId npeId) } /* end of if-else(IX_NPEDL_NPEID_NPEC) */ } /* end of if not IXP42x-A0 Silicon */ - if (TRUE == ixNpeDlNpeStarted[npeId]) + if (true == ixNpeDlNpeStarted[npeId]) { /* NPE has been started. */ return IX_SUCCESS ; @@ -588,7 +588,7 @@ ixNpeDlNpeExecutionStart (IxNpeDlNpeId npeId) if (IX_SUCCESS == status) { /* Indicate NPE has started */ - ixNpeDlNpeStarted[npeId] = TRUE ; + ixNpeDlNpeStarted[npeId] = true ; } IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT, @@ -674,7 +674,7 @@ ixNpeDlNpeExecutionStop (IxNpeDlNpeId npeId) if (IX_SUCCESS == status) { /* Indicate NPE has been stopped */ - ixNpeDlNpeStarted[npeId] = FALSE ; + ixNpeDlNpeStarted[npeId] = false ; } return status; @@ -840,10 +840,10 @@ ixNpeDlNpeInitAndStartInternal (UINT32 *imageLibrary, * currently loaded images. If a critical error occured * during download, record that the NPE has an invalid image */ - status = ixNpeDlNpeMgrImageLoad (npeId, imageCodePtr, TRUE); + status = ixNpeDlNpeMgrImageLoad (npeId, imageCodePtr, true); if (IX_SUCCESS == status) { - ixNpeDlNpeState[npeId].validImage = TRUE; + ixNpeDlNpeState[npeId].validImage = true; ixNpeDlStats.successfulDownloads++; status = ixNpeDlNpeExecutionStart (npeId); @@ -851,7 +851,7 @@ ixNpeDlNpeInitAndStartInternal (UINT32 *imageLibrary, else if ((status == IX_NPEDL_CRITICAL_NPE_ERR) || (status == IX_NPEDL_CRITICAL_MICROCODE_ERR)) { - ixNpeDlNpeState[npeId].validImage = FALSE; + ixNpeDlNpeState[npeId].validImage = false; ixNpeDlStats.criticalFailDownloads++; } diff --git a/drivers/net/npe/IxNpeDlImageMgr.c b/drivers/net/npe/IxNpeDlImageMgr.c index 9bcdc9c..0484483 100644 --- a/drivers/net/npe/IxNpeDlImageMgr.c +++ b/drivers/net/npe/IxNpeDlImageMgr.c @@ -414,11 +414,11 @@ ixNpeDlImageMgrSignatureCheck (UINT32 *microCodeImageLibrary) { IxNpeDlImageMgrImageLibraryHeader *header = (IxNpeDlImageMgrImageLibraryHeader *) microCodeImageLibrary; - BOOL result = TRUE; + BOOL result = true; if (!header || header->signature != IX_NPEDL_IMAGEMGR_SIGNATURE) { - result = FALSE; + result = false; ixNpeDlImageMgrStats.invalidSignature++; } @@ -469,11 +469,11 @@ ixNpeDlImageMgrImageIdCompare ( (imageIdA->major == imageIdB->major) && (imageIdA->minor == imageIdB->minor)) { - return TRUE; + return true; } else { - return FALSE; + return false; } } @@ -491,11 +491,11 @@ ixNpeDlImageMgrNpeFunctionIdCompare ( if ((imageIdA->npeId == imageIdB->npeId) && (imageIdA->functionalityId == imageIdB->functionalityId)) { - return TRUE; + return true; } else { - return FALSE; + return false; } } @@ -550,7 +550,7 @@ ixNpeDlImageMgrImageFind_legacy ( UINT32 imageCount = 0; IX_STATUS status = IX_FAIL; IxNpeDlImageMgrImageLibraryHeader *header; - BOOL imageFound = FALSE; + BOOL imageFound = false; IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT, "Entering ixNpeDlImageMgrImageFind\n"); @@ -584,7 +584,7 @@ ixNpeDlImageMgrImageFind_legacy ( /* get the image size */ *imageSize = header->entry[imageCount].image.size; status = IX_SUCCESS; - imageFound = TRUE; + imageFound = true; } imageCount++; } diff --git a/drivers/net/npe/IxNpeDlNpeMgr.c b/drivers/net/npe/IxNpeDlNpeMgr.c index a9ea8bc..aaffeeb 100644 --- a/drivers/net/npe/IxNpeDlNpeMgr.c +++ b/drivers/net/npe/IxNpeDlNpeMgr.c @@ -229,7 +229,7 @@ static IxNpeDlEcsRegResetValue ixNpeDlEcsRegResetValues[] = static IxNpeDlNpeMgrStats ixNpeDlNpeMgrStats; /* Set when NPE register memory has been mapped */ -static BOOL ixNpeDlMemInitialised = FALSE; +static BOOL ixNpeDlMemInitialised = false; /* @@ -290,7 +290,7 @@ ixNpeDlNpeMgrInit (void) IX_OSAL_ASSERT(virtAddr); ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEC].baseAddress = virtAddr; - ixNpeDlMemInitialised = TRUE; + ixNpeDlMemInitialised = true; } } @@ -314,7 +314,7 @@ ixNpeDlNpeMgrUninit (void) ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEB].baseAddress = 0; ixNpeDlNpeInfo[IX_NPEDL_NPEID_NPEC].baseAddress = 0; - ixNpeDlMemInitialised = FALSE; + ixNpeDlMemInitialised = false; return IX_SUCCESS; } @@ -662,7 +662,7 @@ ixNpeDlNpeMgrNpeReset ( { /* for each physical register in the NPE reg file, write 0 : */ status = ixNpeDlNpeMgrPhysicalRegWrite (npeBaseAddress, regAddr, - 0, TRUE); + 0, true); if (status != IX_SUCCESS) { return status; /* abort reset */ @@ -684,7 +684,7 @@ ixNpeDlNpeMgrNpeReset ( { regVal = ixNpeDlCtxtRegResetValues[ctxtReg]; status = ixNpeDlNpeMgrCtxtRegWrite (npeBaseAddress, ctxtNum, - ctxtReg, regVal, TRUE); + ctxtReg, regVal, true); if (status != IX_SUCCESS) { return status; /* abort reset */ diff --git a/drivers/net/npe/IxNpeMh.c b/drivers/net/npe/IxNpeMh.c index 8703def..2870ff7 100644 --- a/drivers/net/npe/IxNpeMh.c +++ b/drivers/net/npe/IxNpeMh.c @@ -79,7 +79,7 @@ * static variables. */ -PRIVATE BOOL ixNpeMhInitialized = FALSE; +PRIVATE BOOL ixNpeMhInitialized = false; /* * Extern function prototypes. @@ -128,7 +128,7 @@ PUBLIC IX_STATUS ixNpeMhInitialize ( */ ixNpeMhConfigInitialize (npeInterrupts); - ixNpeMhInitialized = TRUE; + ixNpeMhInitialized = true; IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting " "ixNpeMhInitialize\n"); @@ -153,7 +153,7 @@ PUBLIC IX_STATUS ixNpeMhUnload (void) /* Uninitialize the Configuration module */ ixNpeMhConfigUninit (); - ixNpeMhInitialized = FALSE; + ixNpeMhInitialized = false; IX_NPEMH_TRACE0 (IX_NPEMH_FN_ENTRY_EXIT, "Exiting " "ixNpeMhUnload\n"); diff --git a/drivers/net/npe/IxNpeMhConfig.c b/drivers/net/npe/IxNpeMhConfig.c index 50c8f21..092d480 100644 --- a/drivers/net/npe/IxNpeMhConfig.c +++ b/drivers/net/npe/IxNpeMhConfig.c @@ -105,7 +105,7 @@ IxNpeMhConfigNpeInfo ixNpeMhConfigNpeInfo[IX_NPEMH_NUM_NPES] = 0, 0, NULL, - FALSE + false }, { 0, @@ -116,7 +116,7 @@ IxNpeMhConfigNpeInfo ixNpeMhConfigNpeInfo[IX_NPEMH_NUM_NPES] = 0, 0, NULL, - FALSE + false }, { 0, @@ -127,7 +127,7 @@ IxNpeMhConfigNpeInfo ixNpeMhConfigNpeInfo[IX_NPEMH_NUM_NPES] = 0, 0, NULL, - FALSE + false } }; diff --git a/drivers/net/npe/IxNpeMhSend.c b/drivers/net/npe/IxNpeMhSend.c index 318913a..27bc9b7 100644 --- a/drivers/net/npe/IxNpeMhSend.c +++ b/drivers/net/npe/IxNpeMhSend.c @@ -124,7 +124,7 @@ BOOL ixNpeMhSendInFifoIsFull( IxNpeMhNpeId npeId, UINT32 maxSendRetries) { - BOOL isFull = FALSE; + BOOL isFull = false; UINT32 numRetries = 0; /* check the NPE's inFIFO */ diff --git a/drivers/net/npe/IxOsalOsSemaphore.c b/drivers/net/npe/IxOsalOsSemaphore.c index 443aefd..672bec1 100644 --- a/drivers/net/npe/IxOsalOsSemaphore.c +++ b/drivers/net/npe/IxOsalOsSemaphore.c @@ -135,10 +135,10 @@ static void drv_mutex_destroy(IxOsalMutex *mutex) static int drv_mutex_trylock(IxOsalMutex *mutex) { - int result = TRUE; + int result = true; if (*mutex == 1) - result = FALSE; + result = false; return result; } diff --git a/drivers/net/npe/IxQMgrDispatcher.c b/drivers/net/npe/IxQMgrDispatcher.c index 9cb1439..25a3e85 100644 --- a/drivers/net/npe/IxQMgrDispatcher.c +++ b/drivers/net/npe/IxQMgrDispatcher.c @@ -160,7 +160,7 @@ static IxQMgrQId priorityTable[IX_QMGR_MAX_NUM_QUEUES]; /* * This flag indicates to the dispatcher that the priority table needs to be rebuilt. */ -static BOOL rebuildTable = FALSE; +static BOOL rebuildTable = false; /* Dispatcher statistics */ static IxQMgrDispatcherStats dispatcherStats; @@ -197,7 +197,7 @@ ixQMgrDispatcherInit (void) int i; IxFeatureCtrlProductId productId = 0; IxFeatureCtrlDeviceId deviceId = 0; - BOOL stickyIntSilicon = TRUE; + BOOL stickyIntSilicon = true; /* Set default priorities */ for (i=0; i< IX_QMGR_MAX_NUM_QUEUES; i++) @@ -226,7 +226,7 @@ ixQMgrDispatcherInit (void) dispatcherStats.queueStats[i].priorityChangeCnt = 0; dispatcherStats.queueStats[i].intNoCallbackCnt = 0; dispatcherStats.queueStats[i].intLostCallbackCnt = 0; - dispatcherStats.queueStats[i].notificationEnabled = FALSE; + dispatcherStats.queueStats[i].notificationEnabled = false; dispatcherStats.queueStats[i].srcSel = 0; } @@ -258,7 +258,7 @@ ixQMgrDispatcherInit (void) (IX_FEATURE_CTRL_SILICON_TYPE_A0 == (IX_FEATURE_CTRL_SILICON_STEPPING_MASK & productId))) { - stickyIntSilicon = FALSE; + stickyIntSilicon = false; } /* @@ -293,7 +293,7 @@ ixQMgrDispatcherPrioritySet (IxQMgrQId qId, /* Change priority */ dispatchQInfo[qId].priority = priority; /* Set flag */ - rebuildTable = TRUE; + rebuildTable = true; ixOsalIrqUnlock(ixQMgrLockKey); @@ -364,7 +364,7 @@ ixQMgrNotificationEnable (IxQMgrQId qId, #endif #ifndef NDEBUG - dispatcherStats.queueStats[qId].notificationEnabled = TRUE; + dispatcherStats.queueStats[qId].notificationEnabled = true; dispatcherStats.queueStats[qId].srcSel = srcSel; #endif @@ -428,7 +428,7 @@ ixQMgrNotificationDisable (IxQMgrQId qId) * so need critical section */ #ifndef NDEBUG - dispatcherStats.queueStats[qId].notificationEnabled = FALSE; + dispatcherStats.queueStats[qId].notificationEnabled = false; #endif ixQMgrLockKey = ixOsalIrqLock(); @@ -593,7 +593,7 @@ ixQMgrDispatcherLoopRunA0 (IxQMgrDispatchGroup group) qIndex += IX_QMGR_MIN_QUEUPP_QID; } - if (statusChangeFlag == FALSE) + if (statusChangeFlag == false) { /* check if the interrupt register contains * only 1 bit set (happy day scenario) @@ -800,7 +800,7 @@ ixQMgrDispatcherLoopRunB0 (IxQMgrDispatchGroup group) * For example: * intRegVal = 0x0010 * currDispatchQInfo->intRegCheckMask = 0x0010 - * intRegVal == currDispatchQInfo->intRegCheckMask is TRUE. + * intRegVal == currDispatchQInfo->intRegCheckMask is true. */ currDispatchQInfo = &dispatchQInfo[qIndex]; if (intRegVal == currDispatchQInfo->intRegCheckMask) @@ -955,7 +955,7 @@ ixQMgrDispatcherLoopRunB0LLP (IxQMgrDispatchGroup group) * For example: * intRegVal = 0x0010 * currDispatchQInfo->intRegCheckMask = 0x0010 - * intRegVal == currDispatchQInfo->intRegCheckMask is TRUE. + * intRegVal == currDispatchQInfo->intRegCheckMask is true. */ currDispatchQInfo = &dispatchQInfo[qIndex]; if (intRegVal == currDispatchQInfo->intRegCheckMask) @@ -1118,7 +1118,7 @@ ixQMgrDispatcherReBuildPriorityTable (void) int uppQuePriorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX; /* Reset the rebuild flag */ - rebuildTable = FALSE; + rebuildTable = false; /* initialize the mak used to identify the queues in the first half * of the priority table @@ -1266,7 +1266,7 @@ ixQMgrPeriodicDone (void) * Update statistics */ dispatcherStats.queueStats[i].enableCount++; - dispatcherStats.queueStats[i].notificationEnabled = TRUE; + dispatcherStats.queueStats[i].notificationEnabled = true; #endif } } diff --git a/drivers/net/npe/IxQMgrInit.c b/drivers/net/npe/IxQMgrInit.c index b00c22d..61ca96c 100644 --- a/drivers/net/npe/IxQMgrInit.c +++ b/drivers/net/npe/IxQMgrInit.c @@ -66,7 +66,7 @@ * Set to true if initialized * N.B. global so integration/unit tests can reinitialize */ -BOOL qMgrIsInitialized = FALSE; +BOOL qMgrIsInitialized = false; /* * Function definitions. @@ -90,7 +90,7 @@ ixQMgrInit (void) ixQMgrQAccessInit (); /* Initialization complete */ - qMgrIsInitialized = TRUE; + qMgrIsInitialized = true; return IX_SUCCESS; } @@ -107,7 +107,7 @@ ixQMgrUnload (void) ixQMgrQCfgUninit (); /* Uninitialization complete */ - qMgrIsInitialized = FALSE; + qMgrIsInitialized = false; return IX_SUCCESS; } diff --git a/drivers/net/npe/IxQMgrQCfg.c b/drivers/net/npe/IxQMgrQCfg.c index ec7d837..26ec327 100644 --- a/drivers/net/npe/IxQMgrQCfg.c +++ b/drivers/net/npe/IxQMgrQCfg.c @@ -94,7 +94,7 @@ typedef struct char qName[IX_QMGR_MAX_QNAME_LEN+1]; /* Textual description of a queue*/ IxQMgrQSizeInWords qSizeInWords; /* The number of words in the queue */ IxQMgrQEntrySizeInWords qEntrySizeInWords; /* Number of words per queue entry*/ - BOOL isConfigured; /* This flag is TRUE if the queue has + BOOL isConfigured; /* This flag is true if the queue has * been configured */ } IxQMgrCfgQ; @@ -120,7 +120,7 @@ static UINT32 freeSramAddress=0; /* 4 words of zeroed memory for inline access */ static UINT32 zeroedPlaceHolder[4] = { 0, 0, 0, 0 }; -static BOOL cfgInitialized = FALSE; +static BOOL cfgInitialized = false; static IxOsalMutex ixQMgrQCfgMutex; @@ -177,10 +177,10 @@ ixQMgrQCfgInit (void) strcpy (cfgQueueInfo[loopIndex].qName, ""); cfgQueueInfo[loopIndex].qSizeInWords = 0; cfgQueueInfo[loopIndex].qEntrySizeInWords = 0; - cfgQueueInfo[loopIndex].isConfigured = FALSE; + cfgQueueInfo[loopIndex].isConfigured = false; /* Statistics */ - stats.qStats[loopIndex].isConfigured = FALSE; + stats.qStats[loopIndex].isConfigured = false; stats.qStats[loopIndex].qName = cfgQueueInfo[loopIndex].qName; } @@ -191,13 +191,13 @@ ixQMgrQCfgInit (void) ixOsalMutexInit(&ixQMgrQCfgMutex); - cfgInitialized = TRUE; + cfgInitialized = true; } void ixQMgrQCfgUninit (void) { - cfgInitialized = FALSE; + cfgInitialized = false; /* Uninitialise the AqmIf component */ ixQMgrAqmIfUninit (); @@ -281,13 +281,13 @@ ixQMgrQConfig (char *qName, IX_QMGR_QUE_BUFFER_SPACE_SIZE); /* The queue is now configured */ - cfgQueueInfo[qId].isConfigured = TRUE; + cfgQueueInfo[qId].isConfigured = true; ixOsalMutexUnlock(&ixQMgrQCfgMutex); #ifndef NDEBUG /* Update statistics */ - stats.qStats[qId].isConfigured = TRUE; + stats.qStats[qId].isConfigured = true; stats.qStats[qId].qName = cfgQueueInfo[qId].qName; #endif return IX_SUCCESS; @@ -417,7 +417,7 @@ ixQMgrQIsConfigured (IxQMgrQId qId) { if (!IX_QMGR_QID_IS_VALID(qId)) { - return FALSE; + return false; } return cfgQueueInfo[qId].isConfigured; @@ -487,7 +487,7 @@ watermarkLevelIsOk (IxQMgrQId qId, IxQMgrWMLevel level) case IX_QMGR_Q_WM_LEVEL64: break; default: - return FALSE; + return false; } /* Check watermark is not bigger than the qSizeInEntries */ @@ -495,10 +495,10 @@ watermarkLevelIsOk (IxQMgrQId qId, IxQMgrWMLevel level) if ((unsigned)level > qSizeInEntries) { - return FALSE; + return false; } - return TRUE; + return true; } PRIVATE BOOL @@ -512,10 +512,10 @@ qSizeInWordsIsOk (IxQMgrQSizeInWords qSize) case IX_QMGR_Q_SIZE32: case IX_QMGR_Q_SIZE64: case IX_QMGR_Q_SIZE128: - status = TRUE; + status = true; break; default: - status = FALSE; + status = false; break; } @@ -532,10 +532,10 @@ qEntrySizeInWordsIsOk (IxQMgrQEntrySizeInWords entrySize) case IX_QMGR_Q_ENTRY_SIZE1: case IX_QMGR_Q_ENTRY_SIZE2: case IX_QMGR_Q_ENTRY_SIZE4: - status = TRUE; + status = true; break; default: - status = FALSE; + status = false; break; } diff --git a/drivers/net/npe/include/IxAtmdAccCtrl.h b/drivers/net/npe/include/IxAtmdAccCtrl.h index 50ef582..7b87345 100644 --- a/drivers/net/npe/include/IxAtmdAccCtrl.h +++ b/drivers/net/npe/include/IxAtmdAccCtrl.h @@ -1933,12 +1933,12 @@ PUBLIC IX_STATUS ixAtmdAccPortDisable (IxAtmLogicalPort port); * @brief disable a PHY logical port * * This function indicates if the port disable for a port has completed. This -* function will return TRUE if the port has never been enabled. +* function will return true if the port has never been enabled. * * @param port @ref IxAtmLogicalPort [in] - logical PHY port [@a IX_UTOPIA_PORT_0 .. @a IX_UTOPIA_MAX_PORTS - 1] * -* @return @li TRUE disable is complete -* @return @li FALSE disable failed, wrong parameter . +* @return @li true disable is complete +* @return @li false disable failed, wrong parameter . * * @note - This function needs internal locks and should not be called * from an interrupt context diff --git a/drivers/net/npe/include/IxEthAcc_p.h b/drivers/net/npe/include/IxEthAcc_p.h index 4e0de82..eda3e30 100644 --- a/drivers/net/npe/include/IxEthAcc_p.h +++ b/drivers/net/npe/include/IxEthAcc_p.h @@ -92,7 +92,7 @@ #define IX_ETH_ACC_PUBLIC -#define IX_ETH_ACC_IS_PORT_VALID(port) ((port) < IX_ETH_ACC_NUMBER_OF_PORTS ? TRUE : FALSE ) +#define IX_ETH_ACC_IS_PORT_VALID(port) ((port) < IX_ETH_ACC_NUMBER_OF_PORTS ? true : false ) @@ -286,7 +286,7 @@ extern IxEthAccPortDataInfo ixEthAccPortData[]; #define IX_ETH_IS_PORT_INITIALIZED(port) (ixEthAccPortData[port].portInitialized) extern BOOL ixEthAccServiceInit; -#define IX_ETH_ACC_IS_SERVICE_INITIALIZED() (ixEthAccServiceInit == TRUE ) +#define IX_ETH_ACC_IS_SERVICE_INITIALIZED() (ixEthAccServiceInit == true ) /* * Maximum number of frames to consume from the Rx Frame Q. diff --git a/drivers/net/npe/include/IxEthDB.h b/drivers/net/npe/include/IxEthDB.h index 1189c9a..dfdfe1a 100644 --- a/drivers/net/npe/include/IxEthDB.h +++ b/drivers/net/npe/include/IxEthDB.h @@ -229,7 +229,7 @@ typedef enum IX_ETH_DB_INTEGER_PROPERTY = 0x1, /**< 4 byte unsigned integer type */ IX_ETH_DB_STRING_PROPERTY = 0x2, /**< NULL-terminated string type of maximum 255 characters (including the terminator) */ IX_ETH_DB_MAC_ADDR_PROPERTY = 0x3, /**< 6 byte MAC address type */ - IX_ETH_DB_BOOL_PROPERTY = 0x4 /**< 4 byte boolean type; can contain only TRUE and FALSE values */ + IX_ETH_DB_BOOL_PROPERTY = 0x4 /**< 4 byte boolean type; can contain only true and false values */ } IxEthDBPropertyType; /* list of supported properties for the IX_ETH_DB_VLAN_QOS feature */ @@ -1427,8 +1427,8 @@ IxEthDBStatus ixEthDBPriorityMappingClassGet(IxEthDBPortId portID, IxEthDBPriori * * @param portID @ref IxEthDBPortId [in] - ID of the port to enable or disable the VLAN ID Egress tagging on * @param vlanID @ref IxEthDBVlanId [in] - VLAN ID to be matched against outgoing frames - * @param enabled BOOL [in] - TRUE to enable Egress VLAN tagging on the port and given VLAN, and - * FALSE to disable Egress VLAN tagging + * @param enabled BOOL [in] - true to enable Egress VLAN tagging on the port and given VLAN, and + * false to disable Egress VLAN tagging * * @retval IX_ETH_DB_SUCCESS operation completed successfully * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier @@ -1450,8 +1450,8 @@ IxEthDBStatus ixEthDBEgressVlanEntryTaggingEnabledSet(IxEthDBPortId portID, IxEt * @param portID [in] - ID of the port to extract the Egress VLAN ID tagging status from * @param vlanID VLAN [in] - ID whose tagging status is to be extracted * @param enabled [in] - user-specifed location where the status is copied to; following - * the successfull execution of this function the value will be TRUE if Egress VLAN - * tagging is enabled for the given port and VLAN ID, and FALSE otherwise + * the successfull execution of this function the value will be true if Egress VLAN + * tagging is enabled for the given port and VLAN ID, and false otherwise * * - Reentrant - no * - ISR Callable - no @@ -1486,8 +1486,8 @@ IxEthDBStatus ixEthDBEgressVlanEntryTaggingEnabledGet(IxEthDBPortId portID, IxEt * @param portID @ref IxEthDBPortId [in] - ID of the port to enable or disable the VLAN ID Egress tagging on * @param vlanIDMin @ref IxEthDBVlanId [in] - start of the VLAN range to be matched against outgoing frames * @param vlanIDMax @ref IxEthDBVlanId [in] - end of the VLAN range to be matched against outgoing frames - * @param enabled BOOL [in] - TRUE to enable Egress VLAN tagging on the port and given VLAN range, - * and FALSE to disable Egress VLAN tagging + * @param enabled BOOL [in] - true to enable Egress VLAN tagging on the port and given VLAN range, + * and false to disable Egress VLAN tagging * * @retval IX_ETH_DB_SUCCESS operation completed successfully * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier @@ -1640,7 +1640,7 @@ IxEthDBStatus ixEthDBIngressVlanTaggingEnabledGet(IxEthDBPortId portID, IxEthDBT * This feature is disabled by default. * * @param portID ID of the port to configure port ID extraction on - * @param enable TRUE to enable port ID extraction and FALSE to disable it + * @param enable true to enable port ID extraction and false to disable it * * @retval IX_ETH_DB_SUCCESS operation completed successfully * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier @@ -1759,7 +1759,7 @@ IxEthDBStatus ixEthDBFeatureCapabilityGet(IxEthDBPortId portID, IxEthDBFeature * * * @param portID @ref IxEthDBPortId [in] - ID of the port to enable or disable the features on (use IX_ETH_DB_ALL_PORTS for all the ports) * @param feature @ref IxEthDBFeature [in] - feature or feature set to enable or disable - * @param enabled BOOL [in] - TRUE to enable the feature and FALSE to disable it + * @param enabled BOOL [in] - true to enable the feature and false to disable it * * @note Certain features, from a functional point of view, cannot be disabled as such at NPE level; * when such features are set to <i>disabled</i> using the EthDB API they will be configured in such @@ -1786,7 +1786,7 @@ IxEthDBStatus ixEthDBFeatureEnable(IxEthDBPortId portID, IxEthDBFeature feature, * * This function returns the availability and status for a feature set. * Note that if more than one feature is selected (e.g. IX_ETH_DB_LEARNING | IX_ETH_DB_FILTERING) - * the "present" and "enabled" return values will be set to TRUE only if all the features in the + * the "present" and "enabled" return values will be set to true only if all the features in the * feature set are present and enabled (not only some). * * @param portID @ref IxEthDBPortId [in] - ID of the port @@ -1873,7 +1873,7 @@ IxEthDBStatus ixEthDBFeaturePropertyGet(IxEthDBPortId portID, IxEthDBFeature fea * - IX_ETH_DB_INTEGER_PROPERTY - 4 bytes are copied from the source location * - IX_ETH_DB_STRING_PROPERTY - the source string will be copied up to the NULL '\0' string terminator, maximum of 255 characters * - IX_ETH_DB_MAC_ADDR_PROPERTY - 6 bytes are copied from the source location - * - IX_ETH_DB_BOOL_PROPERTY - 4 bytes are copied from the source location; the only allowed values are TRUE (1L) and false (0L) + * - IX_ETH_DB_BOOL_PROPERTY - 4 bytes are copied from the source location; the only allowed values are true (1L) and false (0L) * * @see ixEthDBFeaturePropertySet * @@ -2134,7 +2134,7 @@ IxEthDBStatus ixEthDBWiFiBBSIDSet(IxEthDBPortId portID, IxEthDBMacAddr *bbsid); * @brief Sets the STP blocked/unblocked state for a port * * @param portID @ref IxEthDBPortId [in] - ID of the port - * @param blocked BOOL [in] - TRUE to set the port as STP blocked, FALSE to set it as unblocked + * @param blocked BOOL [in] - true to set the port as STP blocked, false to set it as unblocked * * @retval IX_ETH_DB_SUCCESS operation completed successfully * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier @@ -2153,7 +2153,7 @@ IxEthDBStatus ixEthDBSpanningTreeBlockingStateSet(IxEthDBPortId portID, BOOL blo * @brief Retrieves the STP blocked/unblocked state for a port * * @param portID @ref IxEthDBPortId [in] - ID of the port - * @param blocked BOOL * [in] - set to TRUE if the port is STP blocked, FALSE otherwise + * @param blocked BOOL * [in] - set to true if the port is STP blocked, false otherwise * * @retval IX_ETH_DB_SUCCESS operation completed successfully * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier @@ -2214,7 +2214,7 @@ IxEthDBStatus ixEthDBFirewallModeSet(IxEthDBPortId portID, IxEthDBFirewallMode m * NPE image. * * @param portID ID of the port - * @param enable TRUE to enable invalid MAC address filtering and FALSE to disable it + * @param enable true to enable invalid MAC address filtering and false to disable it * * @retval IX_ETH_DB_SUCCESS operation completed successfully * @retval IX_ETH_DB_INVALID_PORT portID is not a valid port identifier diff --git a/drivers/net/npe/include/IxEthDB_p.h b/drivers/net/npe/include/IxEthDB_p.h index ccec7ea..d173d12 100644 --- a/drivers/net/npe/include/IxEthDB_p.h +++ b/drivers/net/npe/include/IxEthDB_p.h @@ -169,9 +169,9 @@ extern int overflowEvent; #define TREE_POOL_SIZE (4000) /**< number of MacTreeNode objects; each entry has 16 bytes */ /* retry policies */ -#define BUSY_RETRY_ENABLED (TRUE) /**< if set to TRUE the API will retry automatically calls returning BUSY */ -#define FOREVER_RETRY (TRUE) /**< if set to TRUE the API will retry forever BUSY calls */ -#define MAX_RETRIES (400) /**< upper retry limit - used only when FOREVER_RETRY is FALSE */ +#define BUSY_RETRY_ENABLED (true) /**< if set to true the API will retry automatically calls returning BUSY */ +#define FOREVER_RETRY (true) /**< if set to true the API will retry forever BUSY calls */ +#define MAX_RETRIES (400) /**< upper retry limit - used only when FOREVER_RETRY is false */ #define BUSY_RETRY_YIELD (5) /**< ticks to yield for every failed retry */ /* event management */ @@ -179,8 +179,8 @@ extern int overflowEvent; #define EVENT_PROCESSING_LIMIT (100) /**< batch processing control size (how many events are extracted from the queue at once) */ /* MAC descriptors */ -#define STATIC_ENTRY (TRUE) -#define DYNAMIC_ENTRY (FALSE) +#define STATIC_ENTRY (true) +#define DYNAMIC_ENTRY (false) /* age reset on next maintenance - incrementing by 1 will reset to 0 */ #define AGE_RESET (0xFFFFFFFF) @@ -270,7 +270,7 @@ extern int overflowEvent; /* gives an empty dependency map */ #define SET_EMPTY_DEPENDENCY_MAP(map) { int i = 0; for (; i < 32 ; i++) map[i] = 0; } -#define IS_EMPTY_DEPENDENCY_MAP(result, map) { int i = 0 ; result = TRUE; for (; i < 32 ; i++) if (map[i] != 0) { result = FALSE; break; }} +#define IS_EMPTY_DEPENDENCY_MAP(result, map) { int i = 0 ; result = true; for (; i < 32 ; i++) if (map[i] != 0) { result = false; break; }} /** * gives a map consisting only of 'portID' @@ -293,12 +293,12 @@ extern int overflowEvent; #define EXCLUDE_PORT_FROM_MAP(map, portID) { map[portID >> 3] &= ~(1 << (portID & 0x7); } /** - * returns TRUE if map1 is a subset of map2 and FALSE otherwise + * returns true if map1 is a subset of map2 and false otherwise */ -#define IS_MAP_SUBSET(result, map1, map2) { int i = 0; result = TRUE; for (; i < 32 ; i++) if ((map1[i] | map2[i]) != map2[i]) result = FALSE; } +#define IS_MAP_SUBSET(result, map1, map2) { int i = 0; result = true; for (; i < 32 ; i++) if ((map1[i] | map2[i]) != map2[i]) result = false; } /** - * returns TRUE is portID is part of map and FALSE otherwise + * returns true is portID is part of map and false otherwise */ #define IS_PORT_INCLUDED(portID, map) ((map[portID >> 3] & (1 << (portID & 0x7))) != 0) @@ -308,9 +308,9 @@ extern int overflowEvent; #define DIFF_MAPS(map, map1, map2) { int i = 0; for (; i < 32 ; i++) map[i] = map1[i] ^ (map1[i] & map2[i]); } /** - * returns TRUE if the maps collide (have at least one port in common) and FALSE otherwise + * returns true if the maps collide (have at least one port in common) and false otherwise */ -#define MAPS_COLLIDE(result, map1, map2) { int i = 0; result = FALSE; for (; i < 32 ; i++) if ((map1[i] & map2[i]) != 0) result = TRUE; } +#define MAPS_COLLIDE(result, map1, map2) { int i = 0; result = false; for (; i < 32 ; i++) if ((map1[i] & map2[i]) != 0) result = true; } /* size (number of ports) of a dependency map */ #define GET_MAP_SIZE(map, size) { int i = 0, b = 0; size = 0; for (; i < 32 ; i++) { char y = map[i]; for (; b < 8 && (y >>= 1); b++) size += (y & 1); }} @@ -415,7 +415,7 @@ typedef union struct { UINT32 age; - BOOL staticEntry; /**< TRUE if this address is static (doesn't age) */ + BOOL staticEntry; /**< true if this address is static (doesn't age) */ } filteringData; struct @@ -492,26 +492,26 @@ typedef void (*IxEthDBNoteWriteFn)(void *address, MacTreeNode *node); typedef struct { - BOOL updateEnabled; /**< TRUE if updates are enabled for port */ - BOOL userControlled; /**< TRUE if the user has manually used ixEthDBPortUpdateEnableSet */ - BOOL treeInitialized; /**< TRUE if the NPE has received an initial tree */ + BOOL updateEnabled; /**< true if updates are enabled for port */ + BOOL userControlled; /**< true if the user has manually used ixEthDBPortUpdateEnableSet */ + BOOL treeInitialized; /**< true if the NPE has received an initial tree */ IxEthDBPortUpdateHandler updateHandler; /**< port update handler routine */ void *npeUpdateZone; /**< port update memory zone */ void *npeGwUpdateZone; /**< port update memory zone for gateways */ void *vlanUpdateZone; /**< port update memory zone for VLAN tables */ MacTreeNode *searchTree; /**< internal search tree, in MacTreeNode representation */ - BOOL searchTreePendingWrite; /**< TRUE if searchTree holds a tree pending write to the port */ + BOOL searchTreePendingWrite; /**< true if searchTree holds a tree pending write to the port */ } PortUpdateMethod; typedef struct { IxEthDBPortId portID; /**< port ID */ - BOOL enabled; /**< TRUE if the port is enabled */ - BOOL agingEnabled; /**< TRUE if aging on this port is enabled */ + BOOL enabled; /**< true if the port is enabled */ + BOOL agingEnabled; /**< true if aging on this port is enabled */ BOOL initialized; IxEthDBPortMap dependencyPortMap; /**< dependency port map for this port */ PortUpdateMethod updateMethod; /**< update method structure */ - BOOL macAddressUploaded; /**< TRUE if the MAC address was uploaded into the port */ + BOOL macAddressUploaded; /**< true if the MAC address was uploaded into the port */ UINT32 maxRxFrameSize; /**< maximum Rx frame size for this port */ UINT32 maxTxFrameSize; /**< maximum Rx frame size for this port */ diff --git a/drivers/net/npe/include/IxEthMii.h b/drivers/net/npe/include/IxEthMii.h index 397253a..93d3b79 100644 --- a/drivers/net/npe/include/IxEthMii.h +++ b/drivers/net/npe/include/IxEthMii.h @@ -83,7 +83,7 @@ * * @brief Scan the MDIO bus for PHYs * This function scans PHY addresses 0 through 31, and sets phyPresent[n] to - * TRUE if a phy is discovered at address n. + * true if a phy is discovered at address n. * * - Reentrant - no * - ISR Callable - no @@ -120,9 +120,9 @@ PUBLIC IX_STATUS ixEthMiiPhyScan(BOOL phyPresent[], UINT32 maxPhyCount); * @pre The MAC on Ethernet Port 2 (NPE C) must be initialised, and generating the MDIO clock. * * @param phyAddr UINT32 [in] - * @param speed100 BOOL [in] - set to TRUE for 100Mbit/s operation, FALSE for 10Mbit/s - * @param fullDuplex BOOL [in] - set to TRUE for Full Duplex, FALSE for Half Duplex - * @param autonegotiate BOOL [in] - set to TRUE to enable autonegotiation + * @param speed100 BOOL [in] - set to true for 100Mbit/s operation, false for 10Mbit/s + * @param fullDuplex BOOL [in] - set to true for Full Duplex, false for Half Duplex + * @param autonegotiate BOOL [in] - set to true to enable autonegotiation * * @return IX_STATUS * - IX_SUCCESS @@ -223,10 +223,10 @@ PUBLIC IX_STATUS ixEthMiiPhyReset(UINT32 phyAddr); * @pre The MAC on Ethernet Port 2 (NPE C) must be initialised, and generating the MDIO clock. * * @param phyAddr UINT32 [in] - the address of the Ethernet PHY (0-31) - * @param linkUp BOOL [out] - set to TRUE if the link is up - * @param speed100 BOOL [out] - set to TRUE indicates 100Mbit/s, FALSE indicates 10Mbit/s - * @param fullDuplex BOOL [out] - set to TRUE indicates Full Duplex, FALSE indicates Half Duplex - * @param autoneg BOOL [out] - set to TRUE indicates autonegotiation is enabled, FALSE indicates autonegotiation is disabled + * @param linkUp BOOL [out] - set to true if the link is up + * @param speed100 BOOL [out] - set to true indicates 100Mbit/s, false indicates 10Mbit/s + * @param fullDuplex BOOL [out] - set to true indicates Full Duplex, false indicates Half Duplex + * @param autoneg BOOL [out] - set to true indicates autonegotiation is enabled, false indicates autonegotiation is disabled * * @return IX_STATUS * - IX_SUCCESS diff --git a/drivers/net/npe/include/IxFeatureCtrl.h b/drivers/net/npe/include/IxFeatureCtrl.h index dabc38e..1662a00 100644 --- a/drivers/net/npe/include/IxFeatureCtrl.h +++ b/drivers/net/npe/include/IxFeatureCtrl.h @@ -706,14 +706,14 @@ ixFeatureCtrlSwConfigurationCheck (IxFeatureCtrlSwConfig swConfigType); * @brief This function enable/disable the specified software configuration. * * Usage Example:<br> - * - ixFeatureCtrlSwConfigurationWrite(IX_FEATURECTRL_ETH_LEARNING, TRUE) is used + * - ixFeatureCtrlSwConfigurationWrite(IX_FEATURECTRL_ETH_LEARNING, true) is used * to enable Ethernet Learning Feature <br> - * - ixFeatureCtrlSwConfigurationWrite(IX_FEATURECTRL_ETH_LEARNING, FALSE) is used + * - ixFeatureCtrlSwConfigurationWrite(IX_FEATURECTRL_ETH_LEARNING, false) is used * to disable Ethernet Learning Feature <br> * * @param swConfigType IxFeatureCtrlSwConfig [in] - the type of a software configuration * defined in IxFeatureCtrlSwConfig enumeration. - * @param enabled BOOL [in] - To enable(TRUE) / disable (FALSE) the specified software + * @param enabled BOOL [in] - To enable(true) / disable (false) the specified software * configuration. * * @return none diff --git a/drivers/net/npe/include/IxHssAcc.h b/drivers/net/npe/include/IxHssAcc.h index 07bb119..52d5716 100644 --- a/drivers/net/npe/include/IxHssAcc.h +++ b/drivers/net/npe/include/IxHssAcc.h @@ -583,12 +583,12 @@ typedef struct */ typedef struct { - BOOL hdlc56kMode; /**< 56kbps(TRUE)/64kbps(FALSE) HDLC */ + BOOL hdlc56kMode; /**< 56kbps(true)/64kbps(false) HDLC */ IxHssAcc56kEndianness hdlc56kEndian; /**< 56kbps data endianness - - ignored if hdlc56kMode is FALSE*/ - BOOL hdlc56kUnusedBitPolarity0; /**< The polarity '0'(TRUE)/'1'(FALSE) of the unused + - ignored if hdlc56kMode is false*/ + BOOL hdlc56kUnusedBitPolarity0; /**< The polarity '0'(true)/'1'(false) of the unused bit while in 56kbps mode - - ignored if hdlc56kMode is FALSE*/ + - ignored if hdlc56kMode is false*/ } IxHssAccHdlcMode; /** @@ -1006,9 +1006,9 @@ ixHssAccPktPortDisconnect (IxHssAccHssPort hssPortId, * to disconnect and it corresponds to the physical E1/T1 trunk i.e. 0, 1, 2, 3 * * @return - * - TRUE The state of this HSS/HDLC port combination is disconnected, + * - true The state of this HSS/HDLC port combination is disconnected, * so if a disconnect was called, it is now completed. - * - FALSE The state of this HSS/HDLC port combination is connected, + * - false The state of this HSS/HDLC port combination is connected, * so if a disconnect was called, it is not yet completed. */ PUBLIC BOOL @@ -1259,7 +1259,7 @@ ixHssAccChanDisconnect (IxHssAccHssPort hssPortId); * identical ports (0-1). * @param *dataRecvd BOOL [out] - This BOOL indicates to the client whether * or not the access component has read any data for the client. If - * FALSE, the other output parameters will not have been written to. + * false, the other output parameters will not have been written to. * @param *rxOffset unsigned [out] - An offset to indicate to the client * where within the receive buffers the NPE has just written the received * data to. diff --git a/drivers/net/npe/include/IxNpeDl.h b/drivers/net/npe/include/IxNpeDl.h index 86f69f4..f514c2e 100644 --- a/drivers/net/npe/include/IxNpeDl.h +++ b/drivers/net/npe/include/IxNpeDl.h @@ -637,7 +637,7 @@ ixNpeDlMicrocodeImageLibraryOverride (UINT32 *clientImageLibrary); * @param imageIdPtr @ref IxNpeDlImageId* [in] - Pointer to Id of the microcode * image to download. * @param verify BOOL [in] - ON/OFF option to verify the download. If ON - * (verify == TRUE), the Downloader will read back + * (verify == true), the Downloader will read back * each word written to the NPE registers to * ensure the download operation was successful. * diff --git a/drivers/net/npe/include/IxNpeDlNpeMgrUtils_p.h b/drivers/net/npe/include/IxNpeDlNpeMgrUtils_p.h index a752f26..876a438 100644 --- a/drivers/net/npe/include/IxNpeDlNpeMgrUtils_p.h +++ b/drivers/net/npe/include/IxNpeDlNpeMgrUtils_p.h @@ -81,7 +81,7 @@ * @param UINT32 [in] npeBaseAddress - Base Address of NPE * @param UINT32 [in] insMemAddress - NPE instruction memory address to write * @param UINT32 [in] insMemData - data to write to instruction memory - * @param BOOL [in] verify - if TRUE, verify the memory location is + * @param BOOL [in] verify - if true, verify the memory location is * written successfully. * * This function is used to write a single word of data to a location in NPE @@ -93,7 +93,7 @@ * @post * * @return - * - IX_FAIL if verify is TRUE and the memory location was not written + * - IX_FAIL if verify is true and the memory location was not written * successfully * - IX_SUCCESS otherwise */ @@ -113,7 +113,7 @@ ixNpeDlNpeMgrInsMemWrite (UINT32 npeBaseAddress, UINT32 insMemAddress, * @param UINT32 [in] npeBaseAddress - Base Address of NPE * @param UINT32 [in] dataMemAddress - NPE data memory address to write * @param UINT32 [in] dataMemData - data to write to NPE data memory - * @param BOOL [in] verify - if TRUE, verify the memory location is + * @param BOOL [in] verify - if true, verify the memory location is * written successfully. * * This function is used to write a single word of data to a location in NPE @@ -125,7 +125,7 @@ ixNpeDlNpeMgrInsMemWrite (UINT32 npeBaseAddress, UINT32 insMemAddress, * @post * * @return - * - IX_FAIL if verify is TRUE and the memory location was not written + * - IX_FAIL if verify is true and the memory location was not written * successfully * - IX_SUCCESS otherwise */ @@ -304,7 +304,7 @@ ixNpeDlNpeMgrDebugInstructionPostExec (UINT32 npeBaseAddress); * @param UINT32 [in] npeBaseAddress - Base Address of NPE * @param UINT32 [in] regAddr - number of the physical register (0-31)* * @param UINT32 [in] regValue - value to write to the physical register - * @param BOOL [in] verify - if TRUE, verify the register is written + * @param BOOL [in] verify - if true, verify the register is written * successfully. * * This function writes a physical register in the NPE data register file. @@ -324,7 +324,7 @@ ixNpeDlNpeMgrDebugInstructionPostExec (UINT32 npeBaseAddress); * a sequence of calls to this function * * @return - * - IX_FAIL if verify is TRUE and the Context Register was not written + * - IX_FAIL if verify is true and the Context Register was not written * successfully * - IX_SUCCESS if Context Register was written successfully * - IX_NPEDL_CRITICAL_NPE_ERR if Context Register was not written @@ -349,7 +349,7 @@ ixNpeDlNpeMgrPhysicalRegWrite (UINT32 npeBaseAddress, UINT32 regAddr, * @param IxNpeDlCtxtRegNum [in] ctxtReg - which Context Store reg to write * @param UINT32 [in] ctxtRegVal - value to write to the Context Store * register - * @param BOOL [in] verify - if TRUE, verify the register is + * @param BOOL [in] verify - if true, verify the register is * written successfully. * * This function writes the contents of a Context Store register in the NPE @@ -366,7 +366,7 @@ ixNpeDlNpeMgrPhysicalRegWrite (UINT32 npeBaseAddress, UINT32 regAddr, * a sequence of calls to this function * * @return - * - IX_FAIL if verify is TRUE and the Context Register was not written + * - IX_FAIL if verify is true and the Context Register was not written * successfully * - IX_SUCCESS if Context Register was written successfully * - IX_NPEDL_CRITICAL_NPE_ERR if Context Register was not written diff --git a/drivers/net/npe/include/IxNpeDlNpeMgr_p.h b/drivers/net/npe/include/IxNpeDlNpeMgr_p.h index b7fb0f0..e25e532 100644 --- a/drivers/net/npe/include/IxNpeDlNpeMgr_p.h +++ b/drivers/net/npe/include/IxNpeDlNpeMgr_p.h @@ -126,7 +126,7 @@ IX_STATUS ixNpeDlNpeMgrUninit (void); * @param IxNpeDlNpeId [in] npeId - Id of target NPE * @param UINT32* [in] imageCodePtr - pointer to image code in image to be * downloaded - * @param BOOL [in] verify - if TRUE, verify each word written to + * @param BOOL [in] verify - if true, verify each word written to * NPE memory. * * This function loads a image containing blocks of microcode onto a diff --git a/drivers/net/npe/include/IxNpeMhConfig_p.h b/drivers/net/npe/include/IxNpeMhConfig_p.h index 375b346..8c8b9ab 100644 --- a/drivers/net/npe/include/IxNpeMhConfig_p.h +++ b/drivers/net/npe/include/IxNpeMhConfig_p.h @@ -110,7 +110,7 @@ typedef struct UINT32 inFifoRegister; /**< inFIFO register virutal address */ UINT32 outFifoRegister; /**< outFIFO register virtual address */ IxNpeMhConfigIsr isr; /**< isr routine for handling interrupt */ - BOOL oldInterruptState; /**< old interrupt state (TRUE => enabled) */ + BOOL oldInterruptState; /**< old interrupt state (true => enabled) */ } IxNpeMhConfigNpeInfo; @@ -250,7 +250,7 @@ void ixNpeMhConfigIsrRegister ( * @param IxNpeMhNpeId npeId (in) - the ID of the NPE whose interrupt will * be enabled. * - * @return Returns the previous state of the interrupt (TRUE => enabled). + * @return Returns the previous state of the interrupt (true => enabled). */ BOOL ixNpeMhConfigNpeInterruptEnable ( @@ -265,7 +265,7 @@ BOOL ixNpeMhConfigNpeInterruptEnable ( * @param IxNpeMhNpeId npeId (in) - the ID of the NPE whose interrupt will * be disabled. * - * @return Returns the previous state of the interrupt (TRUE => enabled). + * @return Returns the previous state of the interrupt (true => enabled). */ BOOL ixNpeMhConfigNpeInterruptDisable ( @@ -293,7 +293,7 @@ IxNpeMhMessageId ixNpeMhConfigMessageIdGet ( * * @param IxNpeMhNpeId npeId (in) - the NPE ID to validate. * - * @return True if the NPE ID is valid, otherwise False. + * @return true if the NPE ID is valid, otherwise false. */ BOOL ixNpeMhConfigNpeIdIsValid ( @@ -340,7 +340,7 @@ void ixNpeMhConfigLockRelease ( * @param IxNpeMhNpeId npeId (in) - The ID of the NPE for which the inFIFO * will be checked. * - * @return True if the inFIFO is empty, otherwise False. + * @return true if the inFIFO is empty, otherwise false. */ IXNPEMHCONFIG_INLINE BOOL ixNpeMhConfigInFifoIsEmpty ( @@ -355,7 +355,7 @@ IXNPEMHCONFIG_INLINE BOOL ixNpeMhConfigInFifoIsEmpty ( * @param IxNpeMhNpeId npeId (in) - The ID of the NPE for which the inFIFO * will be checked. * - * @return True if the inFIFO is full, otherwise False. + * @return true if the inFIFO is full, otherwise false. */ IXNPEMHCONFIG_INLINE BOOL ixNpeMhConfigInFifoIsFull ( @@ -370,7 +370,7 @@ IXNPEMHCONFIG_INLINE BOOL ixNpeMhConfigInFifoIsFull ( * @param IxNpeMhNpeId npeId (in) - The ID of the NPE for which the outFIFO * will be checked. * - * @return True if the outFIFO is empty, otherwise False. + * @return true if the outFIFO is empty, otherwise false. */ IXNPEMHCONFIG_INLINE BOOL ixNpeMhConfigOutFifoIsEmpty ( @@ -385,7 +385,7 @@ IXNPEMHCONFIG_INLINE BOOL ixNpeMhConfigOutFifoIsEmpty ( * @param IxNpeMhNpeId npeId (in) - The ID of the NPE for which the outFIFO * will be checked. * - * @return True if the outFIFO is full, otherwise False. + * @return true if the outFIFO is full, otherwise false. */ IXNPEMHCONFIG_INLINE BOOL ixNpeMhConfigOutFifoIsFull ( diff --git a/drivers/net/npe/include/IxOsal.h b/drivers/net/npe/include/IxOsal.h index 4ca2e45..28c44af 100644 --- a/drivers/net/npe/include/IxOsal.h +++ b/drivers/net/npe/include/IxOsal.h @@ -1204,8 +1204,8 @@ PUBLIC void ixOsalTicksToTimeval (UINT32 ticks, IxOsalTimeval * pTv); * @li Reentrant: yes * @li IRQ safe: yes * - * @return - TRUE if the structures are equal - * - FALSE otherwise + * @return - true if the structures are equal + * - false otherwise * Note: This function is OS-independant */ #define IX_OSAL_TIME_EQ(tvA, tvB) \ @@ -1225,8 +1225,8 @@ PUBLIC void ixOsalTicksToTimeval (UINT32 ticks, IxOsalTimeval * pTv); * @li Reentrant: yes * @li IRQ safe: yes * - * @return - TRUE if tvA < tvB - * - FALSE otherwise + * @return - true if tvA < tvB + * - false otherwise * Note: This function is OS-independent. Implemented by core. */ #define IX_OSAL_TIME_LT(tvA,tvB) \ @@ -1247,8 +1247,8 @@ PUBLIC void ixOsalTicksToTimeval (UINT32 ticks, IxOsalTimeval * pTv); * @li Reentrant: yes * @li IRQ safe: yes * - * @return - TRUE if tvA > tvB - * - FALSE otherwise + * @return - true if tvA > tvB + * - false otherwise * Note: This function is OS-independent. */ #define IX_OSAL_TIME_GT(tvA, tvB) \ diff --git a/drivers/net/npe/include/IxOsalTypes.h b/drivers/net/npe/include/IxOsalTypes.h index a190a70..06e71de 100644 --- a/drivers/net/npe/include/IxOsalTypes.h +++ b/drivers/net/npe/include/IxOsalTypes.h @@ -107,22 +107,6 @@ typedef volatile INT32 VINT32; */ #define IX_OSAL_BILLION (1000000000) -#ifndef TRUE -#define TRUE 1L -#endif - -#if TRUE != 1 -#error TRUE is not defined to 1 -#endif - -#ifndef FALSE -#define FALSE 0L -#endif - -#if FALSE != 0 -#error FALSE is not defined to 0 -#endif - #ifndef NULL #define NULL 0L #endif diff --git a/drivers/net/npe/include/IxPerfProfAcc.h b/drivers/net/npe/include/IxPerfProfAcc.h index 65c0ba9..7e4527a 100644 --- a/drivers/net/npe/include/IxPerfProfAcc.h +++ b/drivers/net/npe/include/IxPerfProfAcc.h @@ -1281,8 +1281,8 @@ ixPerfProfAccXcycleResultsGet ( * Check if Xcycle measuring task is running. * * @return - * - TRUE - Xcycle is running - * - FALSE - Xcycle is not running + * - true - Xcycle is running + * - false - Xcycle is not running * * @li Reentrant : no * @li ISR Callable : no diff --git a/drivers/net/npe/include/IxQMgrAqmIf_p.h b/drivers/net/npe/include/IxQMgrAqmIf_p.h index 4f0f64d..b63c4a9 100644 --- a/drivers/net/npe/include/IxQMgrAqmIf_p.h +++ b/drivers/net/npe/include/IxQMgrAqmIf_p.h @@ -606,10 +606,10 @@ ixQMgrAqmIfQStatusCheck (UINT32 *oldQStatusWords, (newQStatusWords[statusWordOffset] & mask)) && ((newQStatusWords[statusWordOffset] & mask) == checkValue)) { - return TRUE; + return true; } - return FALSE; + return false; } /* @@ -665,7 +665,7 @@ ixQMgrAqmIfQInterruptEnableRegRead (IxQMgrDispatchGroup group, /* * This inline function will read the status bit of a queue - * specified by qId. If reset is TRUE the bit is cleared. + * specified by qId. If reset is true the bit is cleared. */ IX_QMGR_AQMIF_INLINE BOOL ixQMgrAqmIfRegisterBitCheck (IxQMgrQId qId, @@ -707,11 +707,11 @@ ixQMgrAqmIfRegisterBitCheck (IxQMgrQId qId, { ixQMgrAqmIfWordWrite (registerAddress, registerWord & (~actualBitOffset)); } - return TRUE; + return true; } /* Bit not set */ - return FALSE; + return false; } @@ -733,12 +733,12 @@ ixQMgrAqmIfUnderflowCheck (IxQMgrQId qId) IX_QMGR_QUEUOSTAT0_OFFSET, IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD, IX_QMGR_UNDERFLOW_BIT_OFFSET, - TRUE/*reset*/)); + true/*reset*/)); } else { /* Qs 32-63 have no underflow status */ - return FALSE; + return false; } } @@ -755,12 +755,12 @@ ixQMgrAqmIfOverflowCheck (IxQMgrQId qId) IX_QMGR_QUEUOSTAT0_OFFSET, IX_QMGR_QUEUOSTAT_NUM_QUE_PER_WORD, IX_QMGR_OVERFLOW_BIT_OFFSET, - TRUE/*reset*/)); + true/*reset*/)); } else { /* Qs 32-63 have no overflow status */ - return FALSE; + return false; } } @@ -870,7 +870,7 @@ ixQMgrAqmIfQueUppStatRead (IxQMgrQId qId, IX_QMGR_QUEUPPSTAT0_OFFSET, IX_QMGR_QUEUPPSTAT_NUM_QUE_PER_WORD, 0/*relativeBitOffset*/, - FALSE/*!reset*/)) + false/*!reset*/)) { *status |= IX_QMGR_Q_STATUS_NE_BIT_MASK; } @@ -884,7 +884,7 @@ ixQMgrAqmIfQueUppStatRead (IxQMgrQId qId, IX_QMGR_QUEUPPSTAT1_OFFSET, IX_QMGR_QUEUPPSTAT_NUM_QUE_PER_WORD, 0/*relativeBitOffset*/, - FALSE/*!reset*/)) + false/*!reset*/)) { *status |= IX_QMGR_Q_STATUS_F_BIT_MASK; } diff --git a/drivers/net/npe/include/IxSspAcc.h b/drivers/net/npe/include/IxSspAcc.h index 35e7abf..61d911b 100644 --- a/drivers/net/npe/include/IxSspAcc.h +++ b/drivers/net/npe/include/IxSspAcc.h @@ -898,7 +898,7 @@ ixSspAccTxFIFOIntDisable ( * * @brief Enables/disables the loopback mode * - * @param "BOOL [in] loopbackEnable" - True to enable and false to disable. + * @param "BOOL [in] loopbackEnable" - true to enable and false to disable. * * Global Data : * - None. diff --git a/drivers/net/npe/include/IxTimeSyncAcc.h b/drivers/net/npe/include/IxTimeSyncAcc.h index 25effed..52c4c1c 100644 --- a/drivers/net/npe/include/IxTimeSyncAcc.h +++ b/drivers/net/npe/include/IxTimeSyncAcc.h @@ -497,8 +497,8 @@ ixTimeSyncAccTargetTimeInterruptDisable(void); * the Target Time in the IEEE 1588 hardware assist block. If the condition is * true an event flag is set in the hardware. * - * @param ttmPollFlag [out] - TRUE if the target time reached/hit condition event set - * FALSE if the target time reached/hit condition event is + * @param ttmPollFlag [out] - true if the target time reached/hit condition event set + * false if the target time reached/hit condition event is not set * @param targetTime [out] - Capture current targetTime into client provided buffer * @@ -656,9 +656,9 @@ ixTimeSyncAccAuxTimeInterruptDisable(IxTimeSyncAccAuxMode auxMode); * (Master or Slave) * * @param auxMode [in] - Auxiliary Snapshot Register (Slave or Master) to be checked - * @param auxPollFlag [out] - TRUE if the time stamp captured in auxiliary + * @param auxPollFlag [out] - true if the time stamp captured in auxiliary snapshot register - * FALSE if the time stamp not captured in + * false if the time stamp not captured in auxiliary snapshot register * @param auxTime [out] - Copy the current Auxiliary Snapshot Register value into the * client provided buffer diff --git a/drivers/net/npe/npe.c b/drivers/net/npe/npe.c index 1fe3a95..6fc9f86 100644 --- a/drivers/net/npe/npe.c +++ b/drivers/net/npe/npe.c @@ -322,7 +322,7 @@ static int npe_csr_load(void) } /* don't need this for U-Boot */ - ixFeatureCtrlSwConfigurationWrite(IX_FEATURECTRL_ETH_LEARNING, FALSE); + ixFeatureCtrlSwConfigurationWrite(IX_FEATURECTRL_ETH_LEARNING, false); if (ixEthAccInit() != IX_ETH_ACC_SUCCESS) { printf("Error initialising Ethernet access driver!\n"); @@ -647,29 +647,29 @@ int npe_initialize(bd_t * bis) */ if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) == IX_FEATURE_CTRL_COMPONENT_ENABLED) - npe_exists[IX_ETH_PORT_1] = TRUE; + npe_exists[IX_ETH_PORT_1] = true; if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH1) == IX_FEATURE_CTRL_COMPONENT_ENABLED) - npe_exists[IX_ETH_PORT_2] = TRUE; + npe_exists[IX_ETH_PORT_2] = true; break; case IX_FEATURE_CTRL_SILICON_TYPE_A0: /* * If it is A0 Silicon, we enable both as both Eth Coprocessors * are available. */ - npe_exists[IX_ETH_PORT_1] = TRUE; - npe_exists[IX_ETH_PORT_2] = TRUE; + npe_exists[IX_ETH_PORT_1] = true; + npe_exists[IX_ETH_PORT_2] = true; break; } } else if (ixFeatureCtrlDeviceRead() == IX_FEATURE_CTRL_DEVICE_TYPE_IXP46X) { if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) == IX_FEATURE_CTRL_COMPONENT_ENABLED) - npe_exists[IX_ETH_PORT_1] = TRUE; + npe_exists[IX_ETH_PORT_1] = true; if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH1) == IX_FEATURE_CTRL_COMPONENT_ENABLED) - npe_exists[IX_ETH_PORT_2] = TRUE; + npe_exists[IX_ETH_PORT_2] = true; } npe_used[IX_ETH_PORT_1] = 1; diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 8c71901..1dac16a 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -25,6 +25,7 @@ include $(TOPDIR)/config.mk LIB := $(obj)libpower.o +COBJS-$(CONFIG_EXYNOS_TMU) += exynos-tmu.o COBJS-$(CONFIG_FTPMU010_POWER) += ftpmu010.o COBJS-$(CONFIG_TPS6586X_POWER) += tps6586x.o COBJS-$(CONFIG_TWL4030_POWER) += twl4030.o diff --git a/drivers/power/exynos-tmu.c b/drivers/power/exynos-tmu.c new file mode 100644 index 0000000..d4b3e65 --- /dev/null +++ b/drivers/power/exynos-tmu.c @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * Akshay Saraswat <akshay.s@samsung.com> + * + * EXYNOS - Thermal Management Unit + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <errno.h> +#include <fdtdec.h> +#include <tmu.h> +#include <asm/arch/tmu.h> +#include <asm/arch/power.h> + +#define TRIMINFO_RELOAD 1 +#define CORE_EN 1 +#define THERM_TRIP_EN (1 << 12) + +#define INTEN_RISE0 1 +#define INTEN_RISE1 (1 << 4) +#define INTEN_RISE2 (1 << 8) +#define INTEN_FALL0 (1 << 16) +#define INTEN_FALL1 (1 << 20) +#define INTEN_FALL2 (1 << 24) + +#define TRIM_INFO_MASK 0xff + +#define INTCLEAR_RISE0 1 +#define INTCLEAR_RISE1 (1 << 4) +#define INTCLEAR_RISE2 (1 << 8) +#define INTCLEAR_FALL0 (1 << 16) +#define INTCLEAR_FALL1 (1 << 20) +#define INTCLEAR_FALL2 (1 << 24) +#define INTCLEARALL (INTCLEAR_RISE0 | INTCLEAR_RISE1 | \ + INTCLEAR_RISE2 | INTCLEAR_FALL0 | \ + INTCLEAR_FALL1 | INTCLEAR_FALL2) + +/* Tmeperature threshold values for various thermal events */ +struct temperature_params { + /* minimum value in temperature code range */ + unsigned int min_val; + /* maximum value in temperature code range */ + unsigned int max_val; + /* temperature threshold to start warning */ + unsigned int start_warning; + /* temperature threshold CPU tripping */ + unsigned int start_tripping; + /* temperature threshold for HW tripping */ + unsigned int hardware_tripping; +}; + +/* Pre-defined values and thresholds for calibration of current temperature */ +struct tmu_data { + /* pre-defined temperature thresholds */ + struct temperature_params ts; + /* pre-defined efuse range minimum value */ + unsigned int efuse_min_value; + /* pre-defined efuse value for temperature calibration */ + unsigned int efuse_value; + /* pre-defined efuse range maximum value */ + unsigned int efuse_max_value; + /* current temperature sensing slope */ + unsigned int slope; +}; + +/* TMU device specific details and status */ +struct tmu_info { + /* base Address for the TMU */ + unsigned tmu_base; + /* pre-defined values for calibration and thresholds */ + struct tmu_data data; + /* value required for triminfo_25 calibration */ + unsigned int te1; + /* value required for triminfo_85 calibration */ + unsigned int te2; + /* Value for measured data calibration */ + int dc_value; + /* enum value indicating status of the TMU */ + int tmu_state; +}; + +/* Global struct tmu_info variable to store init values */ +static struct tmu_info gbl_info; + +/* + * Get current temperature code from register, + * then calculate and calibrate it's value + * in degree celsius. + * + * @return current temperature of the chip as sensed by TMU + */ +static int get_cur_temp(struct tmu_info *info) +{ + int cur_temp; + struct exynos5_tmu_reg *reg = (struct exynos5_tmu_reg *)info->tmu_base; + + /* + * Temperature code range between min 25 and max 125. + * May run more than once for first call as initial sensing + * has not yet happened. + */ + do { + cur_temp = readl(®->current_temp) & 0xff; + } while (cur_temp == 0 && info->tmu_state == TMU_STATUS_NORMAL); + + /* Calibrate current temperature */ + cur_temp = cur_temp - info->te1 + info->dc_value; + + return cur_temp; +} + +/* + * Monitors status of the TMU device and exynos temperature + * + * @param temp pointer to the current temperature value + * @return enum tmu_status_t value, code indicating event to execute + */ +enum tmu_status_t tmu_monitor(int *temp) +{ + int cur_temp; + struct tmu_data *data = &gbl_info.data; + + if (gbl_info.tmu_state == TMU_STATUS_INIT) + return TMU_STATUS_INIT; + + /* Read current temperature of the SOC */ + cur_temp = get_cur_temp(&gbl_info); + *temp = cur_temp; + + /* Temperature code lies between min 25 and max 125 */ + if (cur_temp >= data->ts.start_tripping && + cur_temp <= data->ts.max_val) { + return TMU_STATUS_TRIPPED; + } else if (cur_temp >= data->ts.start_warning) { + return TMU_STATUS_WARNING; + } else if (cur_temp < data->ts.start_warning && + cur_temp >= data->ts.min_val) { + return TMU_STATUS_NORMAL; + } else { + /* Temperature code does not lie between min 25 and max 125 */ + gbl_info.tmu_state = TMU_STATUS_INIT; + debug("EXYNOS_TMU: Thermal reading failed\n"); + return TMU_STATUS_INIT; + } +} + +/* + * Get TMU specific pre-defined values from FDT + * + * @param info pointer to the tmu_info struct + * @param blob FDT blob + * @return int value, 0 for success + */ +static int get_tmu_fdt_values(struct tmu_info *info, const void *blob) +{ +#ifdef CONFIG_OF_CONTROL + int node; + int error = 0; + + /* Get the node from FDT for TMU */ + node = fdtdec_next_compatible(blob, 0, + COMPAT_SAMSUNG_EXYNOS_TMU); + if (node < 0) { + debug("EXYNOS_TMU: No node for tmu in device tree\n"); + return -1; + } + + /* + * Get the pre-defined TMU specific values from FDT. + * All of these are expected to be correct otherwise + * miscalculation of register values in tmu_setup_parameters + * may result in misleading current temperature. + */ + info->tmu_base = fdtdec_get_addr(blob, node, "reg"); + if (info->tmu_base == FDT_ADDR_T_NONE) { + debug("%s: Missing tmu-base\n", __func__); + return -1; + } + info->data.ts.min_val = fdtdec_get_int(blob, + node, "samsung,min-temp", -1); + error |= info->data.ts.min_val; + info->data.ts.max_val = fdtdec_get_int(blob, + node, "samsung,max-temp", -1); + error |= info->data.ts.max_val; + info->data.ts.start_warning = fdtdec_get_int(blob, + node, "samsung,start-warning", -1); + error |= info->data.ts.start_warning; + info->data.ts.start_tripping = fdtdec_get_int(blob, + node, "samsung,start-tripping", -1); + error |= info->data.ts.start_tripping; + info->data.ts.hardware_tripping = fdtdec_get_int(blob, + node, "samsung,hw-tripping", -1); + error |= info->data.ts.hardware_tripping; + info->data.efuse_min_value = fdtdec_get_int(blob, + node, "samsung,efuse-min-value", -1); + error |= info->data.efuse_min_value; + info->data.efuse_value = fdtdec_get_int(blob, + node, "samsung,efuse-value", -1); + error |= info->data.efuse_value; + info->data.efuse_max_value = fdtdec_get_int(blob, + node, "samsung,efuse-max-value", -1); + error |= info->data.efuse_max_value; + info->data.slope = fdtdec_get_int(blob, + node, "samsung,slope", -1); + error |= info->data.slope; + info->dc_value = fdtdec_get_int(blob, + node, "samsung,dc-value", -1); + error |= info->dc_value; + + if (error == -1) { + debug("fail to get tmu node properties\n"); + return -1; + } +#endif + + return 0; +} + +/* + * Calibrate and calculate threshold values and + * enable interrupt levels + * + * @param info pointer to the tmu_info struct + */ +static void tmu_setup_parameters(struct tmu_info *info) +{ + unsigned int te_code, con; + unsigned int warning_code, trip_code, hwtrip_code; + unsigned int cooling_temp; + unsigned int rising_value; + struct tmu_data *data = &info->data; + struct exynos5_tmu_reg *reg = (struct exynos5_tmu_reg *)info->tmu_base; + + /* Must reload for reading efuse value from triminfo register */ + writel(TRIMINFO_RELOAD, ®->triminfo_control); + + /* Get the compensation parameter */ + te_code = readl(®->triminfo); + info->te1 = te_code & TRIM_INFO_MASK; + info->te2 = ((te_code >> 8) & TRIM_INFO_MASK); + + if ((data->efuse_min_value > info->te1) || + (info->te1 > data->efuse_max_value) + || (info->te2 != 0)) + info->te1 = data->efuse_value; + + /* Get RISING & FALLING Threshold value */ + warning_code = data->ts.start_warning + + info->te1 - info->dc_value; + trip_code = data->ts.start_tripping + + info->te1 - info->dc_value; + hwtrip_code = data->ts.hardware_tripping + + info->te1 - info->dc_value; + + cooling_temp = 0; + + rising_value = ((warning_code << 8) | + (trip_code << 16) | + (hwtrip_code << 24)); + + /* Set interrupt level */ + writel(rising_value, ®->threshold_temp_rise); + writel(cooling_temp, ®->threshold_temp_fall); + + /* + * Init TMU control tuning parameters + * [28:24] VREF - Voltage reference + * [15:13] THERM_TRIP_MODE - Tripping mode + * [12] THERM_TRIP_EN - Thermal tripping enable + * [11:8] BUF_SLOPE_SEL - Gain of amplifier + * [6] THERM_TRIP_BY_TQ_EN - Tripping by TQ pin + */ + writel(data->slope, ®->tmu_control); + + writel(INTCLEARALL, ®->intclear); + + /* TMU core enable */ + con = readl(®->tmu_control); + con |= THERM_TRIP_EN | CORE_EN; + + writel(con, ®->tmu_control); + + /* Enable HW thermal trip */ + set_hw_thermal_trip(); + + /* LEV1 LEV2 interrupt enable */ + writel(INTEN_RISE1 | INTEN_RISE2, ®->inten); +} + +/* + * Initialize TMU device + * + * @param blob FDT blob + * @return int value, 0 for success + */ +int tmu_init(const void *blob) +{ + gbl_info.tmu_state = TMU_STATUS_INIT; + if (get_tmu_fdt_values(&gbl_info, blob) < 0) + goto ret; + + tmu_setup_parameters(&gbl_info); + gbl_info.tmu_state = TMU_STATUS_NORMAL; +ret: + + return gbl_info.tmu_state; +} diff --git a/drivers/rtc/ds1374.c b/drivers/rtc/ds1374.c index d61a228..ec04ec8 100644 --- a/drivers/rtc/ds1374.c +++ b/drivers/rtc/ds1374.c @@ -84,15 +84,6 @@ #define RTC_SR_BIT_AF 0x01 /* Bit 0 = Alarm Flag */ #define RTC_SR_BIT_OSF 0x80 /* Bit 7 - Osc Stop Flag */ -typedef unsigned char boolean_t; - -#ifndef TRUE -#define TRUE ((boolean_t)(0==0)) -#endif -#ifndef FALSE -#define FALSE (!TRUE) -#endif - const char RtcTodAddr[] = { RTC_TOD_CNT_BYTE0_ADDR, RTC_TOD_CNT_BYTE1_ADDR, @@ -101,7 +92,7 @@ const char RtcTodAddr[] = { }; static uchar rtc_read (uchar reg); -static void rtc_write (uchar reg, uchar val, boolean_t set); +static void rtc_write(uchar reg, uchar val, bool set); static void rtc_write_raw (uchar reg, uchar val); /* @@ -185,7 +176,7 @@ int rtc_set (struct rtc_time *tmp){ } /* Start clock */ - rtc_write(RTC_CTL_ADDR, RTC_CTL_BIT_EN_OSC, FALSE); + rtc_write(RTC_CTL_ADDR, RTC_CTL_BIT_EN_OSC, false); return 0; } @@ -202,18 +193,18 @@ void rtc_reset (void){ struct rtc_time tmp; /* clear status flags */ - rtc_write (RTC_SR_ADDR, (RTC_SR_BIT_AF|RTC_SR_BIT_OSF), FALSE); /* clearing OSF and AF */ + rtc_write(RTC_SR_ADDR, (RTC_SR_BIT_AF|RTC_SR_BIT_OSF), false); /* clearing OSF and AF */ /* Initialise DS1374 oriented to MPC8349E-ADS */ rtc_write (RTC_CTL_ADDR, (RTC_CTL_BIT_EN_OSC |RTC_CTL_BIT_WACE - |RTC_CTL_BIT_AIE), FALSE);/* start osc, disable WACE, clear AIE + |RTC_CTL_BIT_AIE), false);/* start osc, disable WACE, clear AIE - set to 0 */ rtc_write (RTC_CTL_ADDR, (RTC_CTL_BIT_WD_ALM |RTC_CTL_BIT_WDSTR |RTC_CTL_BIT_RS1 |RTC_CTL_BIT_RS2 - |RTC_CTL_BIT_BBSQW), TRUE);/* disable WD/ALM, WDSTR set to INT-pin, + |RTC_CTL_BIT_BBSQW), true);/* disable WD/ALM, WDSTR set to INT-pin, set BBSQW and SQW to 32k - set to 1 */ tmp.tm_year = 1970; @@ -229,9 +220,9 @@ void rtc_reset (void){ tmp.tm_year, tmp.tm_mon, tmp.tm_mday, tmp.tm_hour, tmp.tm_min, tmp.tm_sec); - rtc_write(RTC_WD_ALM_CNT_BYTE2_ADDR,0xAC, TRUE); - rtc_write(RTC_WD_ALM_CNT_BYTE1_ADDR,0xDE, TRUE); - rtc_write(RTC_WD_ALM_CNT_BYTE2_ADDR,0xAD, TRUE); + rtc_write(RTC_WD_ALM_CNT_BYTE2_ADDR, 0xAC, true); + rtc_write(RTC_WD_ALM_CNT_BYTE1_ADDR, 0xDE, true); + rtc_write(RTC_WD_ALM_CNT_BYTE2_ADDR, 0xAD, true); } /* @@ -242,9 +233,9 @@ static uchar rtc_read (uchar reg) return (i2c_reg_read (CONFIG_SYS_I2C_RTC_ADDR, reg)); } -static void rtc_write (uchar reg, uchar val, boolean_t set) +static void rtc_write(uchar reg, uchar val, bool set) { - if (set == TRUE) { + if (set == true) { val |= i2c_reg_read (CONFIG_SYS_I2C_RTC_ADDR, reg); i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val); } else { diff --git a/drivers/rtc/mk48t59.c b/drivers/rtc/mk48t59.c index e285823..3af2623 100644 --- a/drivers/rtc/mk48t59.c +++ b/drivers/rtc/mk48t59.c @@ -49,20 +49,6 @@ static void rtc_write (short reg, uchar val) out8(RTC_PORT_DATA, val); } -#elif defined(CONFIG_PCIPPC2) - -#include "../board/pcippc2/pcippc2.h" - -static uchar rtc_read (short reg) -{ - return in8(RTC(reg)); -} - -static void rtc_write (short reg, uchar val) -{ - out8(RTC(reg),val); -} - #elif defined(CONFIG_EVAL5200) static uchar rtc_read (short reg) diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index de3f471..fbc4e97 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -35,7 +35,6 @@ COBJS-$(CONFIG_LPC32XX_HSUART) += lpc32xx_hsuart.o COBJS-$(CONFIG_MCFUART) += mcfuart.o COBJS-$(CONFIG_OPENCORES_YANU) += opencores_yanu.o COBJS-$(CONFIG_SYS_NS16550) += ns16550.o -COBJS-$(CONFIG_S3C64XX) += s3c64xx.o COBJS-$(CONFIG_S5P) += serial_s5p.o COBJS-$(CONFIG_SYS_NS16550_SERIAL) += serial_ns16550.o COBJS-$(CONFIG_IMX_SERIAL) += serial_imx.o diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 87a0917..7f013ab 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -36,17 +36,31 @@ void NS16550_init(NS16550_t com_port, int baud_divisor) { -#if (!defined(CONFIG_SYS_NS16550_BROKEN_TEMT)) +#if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_OMAP34XX)) + /* + * On some OMAP3 devices when UART3 is configured for boot mode before + * SPL starts only THRE bit is set. We have to empty the transmitter + * before initialization starts. + */ + if ((serial_in(&com_port->lsr) & (UART_LSR_TEMT | UART_LSR_THRE)) + == UART_LSR_THRE) { + serial_out(UART_LCR_DLAB, &com_port->lcr); + serial_out(baud_divisor & 0xff, &com_port->dll); + serial_out((baud_divisor >> 8) & 0xff, &com_port->dlm); + serial_out(UART_LCRVAL, &com_port->lcr); + serial_out(0, &com_port->mdr1); + } +#endif + while (!(serial_in(&com_port->lsr) & UART_LSR_TEMT)) ; -#endif serial_out(CONFIG_SYS_NS16550_IER, &com_port->ier); #if (defined(CONFIG_OMAP) && !defined(CONFIG_OMAP3_ZOOM2)) || \ - defined(CONFIG_AM33XX) + defined(CONFIG_AM33XX) || defined(CONFIG_TI814X) serial_out(0x7, &com_port->mdr1); /* mode select reset TL16C750*/ #endif - serial_out(UART_LCR_BKSE | UART_LCRVAL, (ulong)&com_port->lcr); + serial_out(UART_LCR_BKSE | UART_LCRVAL, &com_port->lcr); serial_out(0, &com_port->dll); serial_out(0, &com_port->dlm); serial_out(UART_LCRVAL, &com_port->lcr); @@ -57,7 +71,8 @@ void NS16550_init(NS16550_t com_port, int baud_divisor) serial_out((baud_divisor >> 8) & 0xff, &com_port->dlm); serial_out(UART_LCRVAL, &com_port->lcr); #if (defined(CONFIG_OMAP) && !defined(CONFIG_OMAP3_ZOOM2)) || \ - defined(CONFIG_AM33XX) || defined(CONFIG_SOC_DA8XX) + defined(CONFIG_AM33XX) || defined(CONFIG_SOC_DA8XX) || \ + defined(CONFIG_TI814X) #if defined(CONFIG_APTIX) /* /13 mode so Aptix 6MHz can hit 115200 */ diff --git a/drivers/serial/s3c64xx.c b/drivers/serial/s3c64xx.c deleted file mode 100644 index b590992..0000000 --- a/drivers/serial/s3c64xx.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * (C) Copyright 2002 - * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> - * - * (C) Copyright 2008 - * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <common.h> -#include <linux/compiler.h> -#include <serial.h> -#include <asm/arch/s3c6400.h> - -DECLARE_GLOBAL_DATA_PTR; - -#ifdef CONFIG_SERIAL1 -#define UART_NR S3C64XX_UART0 - -#elif defined(CONFIG_SERIAL2) -#define UART_NR S3C64XX_UART1 - -#elif defined(CONFIG_SERIAL3) -#define UART_NR S3C64XX_UART2 - -#else -#error "Bad: you didn't configure serial ..." -#endif - -/* - * The coefficient, used to calculate the baudrate on S3C6400 UARTs is - * calculated as - * C = UBRDIV * 16 + number_of_set_bits_in_UDIVSLOT - * however, section 31.6.11 of the datasheet doesn't recomment using 1 for 1, - * 3 for 2, ... (2^n - 1) for n, instead, they suggest using these constants: - */ -static const int udivslot[] = { - 0, - 0x0080, - 0x0808, - 0x0888, - 0x2222, - 0x4924, - 0x4a52, - 0x54aa, - 0x5555, - 0xd555, - 0xd5d5, - 0xddd5, - 0xdddd, - 0xdfdd, - 0xdfdf, - 0xffdf, -}; - -static void s3c64xx_serial_setbrg(void) -{ - s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR); - u32 pclk = get_PCLK(); - u32 baudrate = gd->baudrate; - int i; - - i = (pclk / baudrate) % 16; - - uart->UBRDIV = pclk / baudrate / 16 - 1; - uart->UDIVSLOT = udivslot[i]; - - for (i = 0; i < 100; i++) - barrier(); -} - -/* - * Initialise the serial port with the given baudrate. The settings - * are always 8 data bits, no parity, 1 stop bit, no start bits. - */ -static int s3c64xx_serial_init(void) -{ - s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR); - - /* reset and enable FIFOs, set triggers to the maximum */ - uart->UFCON = 0xff; - uart->UMCON = 0; - /* 8N1 */ - uart->ULCON = 3; - /* No interrupts, no DMA, pure polling */ - uart->UCON = 5; - - serial_setbrg(); - - return 0; -} - -/* - * Read a single byte from the serial port. Returns 1 on success, 0 - * otherwise. When the function is succesfull, the character read is - * written into its argument c. - */ -static int s3c64xx_serial_getc(void) -{ - s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR); - - /* wait for character to arrive */ - while (!(uart->UTRSTAT & 0x1)); - - return uart->URXH & 0xff; -} - -#ifdef CONFIG_MODEM_SUPPORT -static int be_quiet; -void disable_putc(void) -{ - be_quiet = 1; -} - -void enable_putc(void) -{ - be_quiet = 0; -} -#endif - - -/* - * Output a single byte to the serial port. - */ -static void s3c64xx_serial_putc(const char c) -{ - s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR); - -#ifdef CONFIG_MODEM_SUPPORT - if (be_quiet) - return; -#endif - - /* wait for room in the tx FIFO */ - while (!(uart->UTRSTAT & 0x2)); - - uart->UTXH = c; - - /* If \n, also do \r */ - if (c == '\n') - serial_putc('\r'); -} - -/* - * Test whether a character is in the RX buffer - */ -static int s3c64xx_serial_tstc(void) -{ - s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR); - - return uart->UTRSTAT & 0x1; -} - -static struct serial_device s3c64xx_serial_drv = { - .name = "s3c64xx_serial", - .start = s3c64xx_serial_init, - .stop = NULL, - .setbrg = s3c64xx_serial_setbrg, - .putc = s3c64xx_serial_putc, - .puts = default_serial_puts, - .getc = s3c64xx_serial_getc, - .tstc = s3c64xx_serial_tstc, -}; - -void s3c64xx_serial_initialize(void) -{ - serial_register(&s3c64xx_serial_drv); -} - -__weak struct serial_device *default_serial_console(void) -{ - return &s3c64xx_serial_drv; -} diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c index 7922bf0..9f04643 100644 --- a/drivers/serial/serial.c +++ b/drivers/serial/serial.c @@ -165,7 +165,6 @@ serial_initfunc(atmel_serial_initialize); serial_initfunc(lpc32xx_serial_initialize); serial_initfunc(mcf_serial_initialize); serial_initfunc(oc_serial_initialize); -serial_initfunc(s3c64xx_serial_initialize); serial_initfunc(sandbox_serial_initialize); serial_initfunc(clps7111_serial_initialize); serial_initfunc(imx_serial_initialize); @@ -259,7 +258,6 @@ void serial_initialize(void) lpc32xx_serial_initialize(); mcf_serial_initialize(); oc_serial_initialize(); - s3c64xx_serial_initialize(); sandbox_serial_initialize(); clps7111_serial_initialize(); imx_serial_initialize(); diff --git a/drivers/serial/usbtty.c b/drivers/serial/usbtty.c index e47cb9a..8e08153 100644 --- a/drivers/serial/usbtty.c +++ b/drivers/serial/usbtty.c @@ -63,7 +63,7 @@ /* * Buffers to hold input and output data */ -#define USBTTY_BUFFER_SIZE 256 +#define USBTTY_BUFFER_SIZE 2048 static circbuf_t usbtty_input; static circbuf_t usbtty_output; @@ -971,8 +971,8 @@ static void usbtty_event_handler (struct usb_device_instance *device, /* * is_usbd_high_speed routine needs to be defined by * specific gadget driver - * It returns TRUE if device enumerates at High speed - * Retuns FALSE otherwise + * It returns true if device enumerates at High speed + * Retuns false otherwise */ for (i = 0; i < NUM_ENDPOINTS; i++) { if (((ep_descriptor_ptrs[i]->bmAttributes & diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile index 8fdffb1..1987ca1 100644 --- a/drivers/sound/Makefile +++ b/drivers/sound/Makefile @@ -28,6 +28,7 @@ LIB := $(obj)libsound.o COBJS-$(CONFIG_SOUND) += sound.o COBJS-$(CONFIG_I2S) += samsung-i2s.o COBJS-$(CONFIG_SOUND_WM8994) += wm8994.o +COBJS-$(CONFIG_SOUND_MAX98095) += max98095.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/sound/max98095.c b/drivers/sound/max98095.c new file mode 100644 index 0000000..d69db58 --- /dev/null +++ b/drivers/sound/max98095.c @@ -0,0 +1,550 @@ +/* + * max98095.c -- MAX98095 ALSA SoC Audio driver + * + * Copyright 2011 Maxim Integrated Products + * + * Modified for uboot by R. Chandrasekar (rcsekar@samsung.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <asm/arch/clk.h> +#include <asm/arch/cpu.h> +#include <asm/arch/power.h> +#include <asm/gpio.h> +#include <asm/io.h> +#include <common.h> +#include <div64.h> +#include <fdtdec.h> +#include <i2c.h> +#include <sound.h> +#include "i2s.h" +#include "max98095.h" + +enum max98095_type { + MAX98095, +}; + +struct max98095_priv { + enum max98095_type devtype; + unsigned int sysclk; + unsigned int rate; + unsigned int fmt; +}; + +static struct sound_codec_info g_codec_info; +struct max98095_priv g_max98095_info; +unsigned int g_max98095_i2c_dev_addr; + +/* Index 0 is reserved. */ +int rate_table[] = {0, 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, + 88200, 96000}; + +/* + * Writes value to a device register through i2c + * + * @param reg reg number to be write + * @param data data to be writen to the above registor + * + * @return int value 1 for change, 0 for no change or negative error code. + */ +static int max98095_i2c_write(unsigned int reg, unsigned char data) +{ + debug("%s: Write Addr : 0x%02X, Data : 0x%02X\n", + __func__, reg, data); + return i2c_write(g_max98095_i2c_dev_addr, reg, 1, &data, 1); +} + +/* + * Read a value from a device register through i2c + * + * @param reg reg number to be read + * @param data address of read data to be stored + * + * @return int value 0 for success, -1 in case of error. + */ +static unsigned int max98095_i2c_read(unsigned int reg, unsigned char *data) +{ + int ret; + + ret = i2c_read(g_max98095_i2c_dev_addr, reg, 1, data, 1); + if (ret != 0) { + debug("%s: Error while reading register %#04x\n", + __func__, reg); + return -1; + } + + return 0; +} + +/* + * update device register bits through i2c + * + * @param reg codec register + * @param mask register mask + * @param value new value + * + * @return int value 0 for success, non-zero error code. + */ +static int max98095_update_bits(unsigned int reg, unsigned char mask, + unsigned char value) +{ + int change, ret = 0; + unsigned char old, new; + + if (max98095_i2c_read(reg, &old) != 0) + return -1; + new = (old & ~mask) | (value & mask); + change = (old != new) ? 1 : 0; + if (change) + ret = max98095_i2c_write(reg, new); + if (ret < 0) + return ret; + + return change; +} + +/* + * codec mclk clock divider coefficients based on sampling rate + * + * @param rate sampling rate + * @param value address of indexvalue to be stored + * + * @return 0 for success or negative error code. + */ +static int rate_value(int rate, u8 *value) +{ + int i; + + for (i = 1; i < ARRAY_SIZE(rate_table); i++) { + if (rate_table[i] >= rate) { + *value = i; + return 0; + } + } + *value = 1; + + return -1; +} + +/* + * Sets hw params for max98095 + * + * @param max98095 max98095 information pointer + * @param rate Sampling rate + * @param bits_per_sample Bits per sample + * + * @return -1 for error and 0 Success. + */ +static int max98095_hw_params(struct max98095_priv *max98095, + unsigned int rate, unsigned int bits_per_sample) +{ + u8 regval; + int error; + + switch (bits_per_sample) { + case 16: + error = max98095_update_bits(M98095_034_DAI2_FORMAT, + M98095_DAI_WS, 0); + break; + case 24: + error = max98095_update_bits(M98095_034_DAI2_FORMAT, + M98095_DAI_WS, M98095_DAI_WS); + break; + default: + debug("%s: Illegal bits per sample %d.\n", + __func__, bits_per_sample); + return -1; + } + + if (rate_value(rate, ®val)) { + debug("%s: Failed to set sample rate to %d.\n", + __func__, rate); + return -1; + } + max98095->rate = rate; + + error |= max98095_update_bits(M98095_031_DAI2_CLKMODE, + M98095_CLKMODE_MASK, regval); + + /* Update sample rate mode */ + if (rate < 50000) + error |= max98095_update_bits(M98095_038_DAI2_FILTERS, + M98095_DAI_DHF, 0); + else + error |= max98095_update_bits(M98095_038_DAI2_FILTERS, + M98095_DAI_DHF, M98095_DAI_DHF); + + if (error < 0) { + debug("%s: Error setting hardware params.\n", __func__); + return -1; + } + + return 0; +} + +/* + * Configures Audio interface system clock for the given frequency + * + * @param max98095 max98095 information + * @param freq Sampling frequency in Hz + * + * @return -1 for error and 0 success. + */ +static int max98095_set_sysclk(struct max98095_priv *max98095, + unsigned int freq) +{ + int error = 0; + + /* Requested clock frequency is already setup */ + if (freq == max98095->sysclk) + return 0; + + /* Setup clocks for slave mode, and using the PLL + * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) + * 0x02 (when master clk is 20MHz to 40MHz).. + * 0x03 (when master clk is 40MHz to 60MHz).. + */ + if ((freq >= 10000000) && (freq < 20000000)) { + error = max98095_i2c_write(M98095_026_SYS_CLK, 0x10); + } else if ((freq >= 20000000) && (freq < 40000000)) { + error = max98095_i2c_write(M98095_026_SYS_CLK, 0x20); + } else if ((freq >= 40000000) && (freq < 60000000)) { + error = max98095_i2c_write(M98095_026_SYS_CLK, 0x30); + } else { + debug("%s: Invalid master clock frequency\n", __func__); + return -1; + } + + debug("%s: Clock at %uHz\n", __func__, freq); + + if (error < 0) + return -1; + + max98095->sysclk = freq; + return 0; +} + +/* + * Sets Max98095 I2S format + * + * @param max98095 max98095 information + * @param fmt i2S format - supports a subset of the options defined + * in i2s.h. + * + * @return -1 for error and 0 Success. + */ +static int max98095_set_fmt(struct max98095_priv *max98095, int fmt) +{ + u8 regval = 0; + int error = 0; + + if (fmt == max98095->fmt) + return 0; + + max98095->fmt = fmt; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + /* Slave mode PLL */ + error |= max98095_i2c_write(M98095_032_DAI2_CLKCFG_HI, + 0x80); + error |= max98095_i2c_write(M98095_033_DAI2_CLKCFG_LO, + 0x00); + break; + case SND_SOC_DAIFMT_CBM_CFM: + /* Set to master mode */ + regval |= M98095_DAI_MAS; + break; + case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBM_CFS: + default: + debug("%s: Clock mode unsupported\n", __func__); + return -1; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + regval |= M98095_DAI_DLY; + break; + case SND_SOC_DAIFMT_LEFT_J: + break; + default: + debug("%s: Unrecognized format.\n", __func__); + return -1; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_NB_IF: + regval |= M98095_DAI_WCI; + break; + case SND_SOC_DAIFMT_IB_NF: + regval |= M98095_DAI_BCI; + break; + case SND_SOC_DAIFMT_IB_IF: + regval |= M98095_DAI_BCI | M98095_DAI_WCI; + break; + default: + debug("%s: Unrecognized inversion settings.\n", __func__); + return -1; + } + + error |= max98095_update_bits(M98095_034_DAI2_FORMAT, + M98095_DAI_MAS | M98095_DAI_DLY | M98095_DAI_BCI | + M98095_DAI_WCI, regval); + + error |= max98095_i2c_write(M98095_035_DAI2_CLOCK, + M98095_DAI_BSEL64); + + if (error < 0) { + debug("%s: Error setting i2s format.\n", __func__); + return -1; + } + + return 0; +} + +/* + * resets the audio codec + * + * @return -1 for error and 0 success. + */ +static int max98095_reset(void) +{ + int i, ret; + + /* + * Gracefully reset the DSP core and the codec hardware in a proper + * sequence. + */ + ret = max98095_i2c_write(M98095_00F_HOST_CFG, 0); + if (ret != 0) { + debug("%s: Failed to reset DSP: %d\n", __func__, ret); + return ret; + } + + ret = max98095_i2c_write(M98095_097_PWR_SYS, 0); + if (ret != 0) { + debug("%s: Failed to reset codec: %d\n", __func__, ret); + return ret; + } + + /* + * Reset to hardware default for registers, as there is not a soft + * reset hardware control register. + */ + for (i = M98095_010_HOST_INT_CFG; i < M98095_REG_MAX_CACHED; i++) { + ret = max98095_i2c_write(i, 0); + if (ret < 0) { + debug("%s: Failed to reset: %d\n", __func__, ret); + return ret; + } + } + + return 0; +} + +/* + * Intialise max98095 codec device + * + * @param max98095 max98095 information + * + * @returns -1 for error and 0 Success. + */ +static int max98095_device_init(struct max98095_priv *max98095) +{ + unsigned char id; + int error = 0; + + /* reset the codec, the DSP core, and disable all interrupts */ + error = max98095_reset(); + if (error != 0) { + debug("Reset\n"); + return error; + } + + /* initialize private data */ + max98095->sysclk = -1U; + max98095->rate = -1U; + max98095->fmt = -1U; + + error = max98095_i2c_read(M98095_0FF_REV_ID, &id); + if (error < 0) { + debug("%s: Failure reading hardware revision: %d\n", + __func__, id); + goto err_access; + } + debug("%s: Hardware revision: %c\n", __func__, (id - 0x40) + 'A'); + + error |= max98095_i2c_write(M98095_097_PWR_SYS, M98095_PWRSV); + + /* + * initialize registers to hardware default configuring audio + * interface2 to DAC + */ + error |= max98095_i2c_write(M98095_048_MIX_DAC_LR, + M98095_DAI2M_TO_DACL|M98095_DAI2M_TO_DACR); + + error |= max98095_i2c_write(M98095_092_PWR_EN_OUT, + M98095_SPK_SPREADSPECTRUM); + error |= max98095_i2c_write(M98095_045_CFG_DSP, M98095_DSPNORMAL); + error |= max98095_i2c_write(M98095_04E_CFG_HP, M98095_HPNORMAL); + + error |= max98095_i2c_write(M98095_02C_DAI1_IOCFG, + M98095_S1NORMAL|M98095_SDATA); + + error |= max98095_i2c_write(M98095_036_DAI2_IOCFG, + M98095_S2NORMAL|M98095_SDATA); + + error |= max98095_i2c_write(M98095_040_DAI3_IOCFG, + M98095_S3NORMAL|M98095_SDATA); + + /* take the codec out of the shut down */ + error |= max98095_update_bits(M98095_097_PWR_SYS, M98095_SHDNRUN, + M98095_SHDNRUN); + /* route DACL and DACR output to HO and Spekers */ + error |= max98095_i2c_write(M98095_050_MIX_SPK_LEFT, 0x01); /* DACL */ + error |= max98095_i2c_write(M98095_051_MIX_SPK_RIGHT, 0x01);/* DACR */ + error |= max98095_i2c_write(M98095_04C_MIX_HP_LEFT, 0x01); /* DACL */ + error |= max98095_i2c_write(M98095_04D_MIX_HP_RIGHT, 0x01); /* DACR */ + + /* power Enable */ + error |= max98095_i2c_write(M98095_091_PWR_EN_OUT, 0xF3); + + /* set Volume */ + error |= max98095_i2c_write(M98095_064_LVL_HP_L, 15); + error |= max98095_i2c_write(M98095_065_LVL_HP_R, 15); + error |= max98095_i2c_write(M98095_067_LVL_SPK_L, 16); + error |= max98095_i2c_write(M98095_068_LVL_SPK_R, 16); + + /* Enable DAIs */ + error |= max98095_i2c_write(M98095_093_BIAS_CTRL, 0x30); + error |= max98095_i2c_write(M98095_096_PWR_DAC_CK, 0x07); + +err_access: + if (error < 0) + return -1; + + return 0; +} + +static int max98095_do_init(struct sound_codec_info *pcodec_info, + int sampling_rate, int mclk_freq, + int bits_per_sample) +{ + int ret = 0; + + /* Enable codec clock */ + set_xclkout(); + + /* shift the device address by 1 for 7 bit addressing */ + g_max98095_i2c_dev_addr = pcodec_info->i2c_dev_addr >> 1; + + if (pcodec_info->codec_type == CODEC_MAX_98095) + g_max98095_info.devtype = MAX98095; + else { + debug("%s: Codec id [%d] not defined\n", __func__, + pcodec_info->codec_type); + return -1; + } + + ret = max98095_device_init(&g_max98095_info); + if (ret < 0) { + debug("%s: max98095 codec chip init failed\n", __func__); + return ret; + } + + ret = max98095_set_sysclk(&g_max98095_info, mclk_freq); + if (ret < 0) { + debug("%s: max98095 codec set sys clock failed\n", __func__); + return ret; + } + + ret = max98095_hw_params(&g_max98095_info, sampling_rate, + bits_per_sample); + + if (ret == 0) { + ret = max98095_set_fmt(&g_max98095_info, + SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS); + } + + return ret; +} + +static int get_max98095_codec_values(struct sound_codec_info *pcodec_info, + const void *blob) +{ + int error = 0; +#ifdef CONFIG_OF_CONTROL + enum fdt_compat_id compat; + int node; + int parent; + + /* Get the node from FDT for codec */ + node = fdtdec_next_compatible(blob, 0, COMPAT_MAXIM_98095_CODEC); + if (node <= 0) { + debug("EXYNOS_SOUND: No node for codec in device tree\n"); + debug("node = %d\n", node); + return -1; + } + + parent = fdt_parent_offset(blob, node); + if (parent < 0) { + debug("%s: Cannot find node parent\n", __func__); + return -1; + } + + compat = fdtdec_lookup(blob, parent); + switch (compat) { + case COMPAT_SAMSUNG_S3C2440_I2C: + pcodec_info->i2c_bus = i2c_get_bus_num_fdt(parent); + error |= pcodec_info->i2c_bus; + debug("i2c bus = %d\n", pcodec_info->i2c_bus); + pcodec_info->i2c_dev_addr = fdtdec_get_int(blob, node, + "reg", 0); + error |= pcodec_info->i2c_dev_addr; + debug("i2c dev addr = %x\n", pcodec_info->i2c_dev_addr); + break; + default: + debug("%s: Unknown compat id %d\n", __func__, compat); + return -1; + } +#else + pcodec_info->i2c_bus = AUDIO_I2C_BUS; + pcodec_info->i2c_dev_addr = AUDIO_I2C_REG; + debug("i2c dev addr = %d\n", pcodec_info->i2c_dev_addr); +#endif + pcodec_info->codec_type = CODEC_MAX_98095; + if (error == -1) { + debug("fail to get max98095 codec node properties\n"); + return -1; + } + + return 0; +} + +/* max98095 Device Initialisation */ +int max98095_init(const void *blob, int sampling_rate, int mclk_freq, + int bits_per_sample) +{ + int ret; + int old_bus = i2c_get_bus_num(); + struct sound_codec_info *pcodec_info = &g_codec_info; + + if (get_max98095_codec_values(pcodec_info, blob) < 0) { + debug("FDT Codec values failed\n"); + return -1; + } + + i2c_set_bus_num(pcodec_info->i2c_bus); + ret = max98095_do_init(pcodec_info, sampling_rate, mclk_freq, + bits_per_sample); + i2c_set_bus_num(old_bus); + + return ret; +} diff --git a/drivers/sound/max98095.h b/drivers/sound/max98095.h new file mode 100644 index 0000000..ae5eb14 --- /dev/null +++ b/drivers/sound/max98095.h @@ -0,0 +1,311 @@ +/* + * max98095.h -- MAX98095 ALSA SoC Audio driver + * + * Copyright 2011 Maxim Integrated Products + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _MAX98095_H +#define _MAX98095_H + +/* + * MAX98095 Registers Definition + */ + +#define M98095_000_HOST_DATA 0x00 +#define M98095_001_HOST_INT_STS 0x01 +#define M98095_002_HOST_RSP_STS 0x02 +#define M98095_003_HOST_CMD_STS 0x03 +#define M98095_004_CODEC_STS 0x04 +#define M98095_005_DAI1_ALC_STS 0x05 +#define M98095_006_DAI2_ALC_STS 0x06 +#define M98095_007_JACK_AUTO_STS 0x07 +#define M98095_008_JACK_MANUAL_STS 0x08 +#define M98095_009_JACK_VBAT_STS 0x09 +#define M98095_00A_ACC_ADC_STS 0x0A +#define M98095_00B_MIC_NG_AGC_STS 0x0B +#define M98095_00C_SPK_L_VOLT_STS 0x0C +#define M98095_00D_SPK_R_VOLT_STS 0x0D +#define M98095_00E_TEMP_SENSOR_STS 0x0E +#define M98095_00F_HOST_CFG 0x0F +#define M98095_010_HOST_INT_CFG 0x10 +#define M98095_011_HOST_INT_EN 0x11 +#define M98095_012_CODEC_INT_EN 0x12 +#define M98095_013_JACK_INT_EN 0x13 +#define M98095_014_JACK_INT_EN 0x14 +#define M98095_015_DEC 0x15 +#define M98095_016_RESERVED 0x16 +#define M98095_017_RESERVED 0x17 +#define M98095_018_KEYCODE3 0x18 +#define M98095_019_KEYCODE2 0x19 +#define M98095_01A_KEYCODE1 0x1A +#define M98095_01B_KEYCODE0 0x1B +#define M98095_01C_OEMCODE1 0x1C +#define M98095_01D_OEMCODE0 0x1D +#define M98095_01E_XCFG1 0x1E +#define M98095_01F_XCFG2 0x1F +#define M98095_020_XCFG3 0x20 +#define M98095_021_XCFG4 0x21 +#define M98095_022_XCFG5 0x22 +#define M98095_023_XCFG6 0x23 +#define M98095_024_XGPIO 0x24 +#define M98095_025_XCLKCFG 0x25 +#define M98095_026_SYS_CLK 0x26 +#define M98095_027_DAI1_CLKMODE 0x27 +#define M98095_028_DAI1_CLKCFG_HI 0x28 +#define M98095_029_DAI1_CLKCFG_LO 0x29 +#define M98095_02A_DAI1_FORMAT 0x2A +#define M98095_02B_DAI1_CLOCK 0x2B +#define M98095_02C_DAI1_IOCFG 0x2C +#define M98095_02D_DAI1_TDM 0x2D +#define M98095_02E_DAI1_FILTERS 0x2E +#define M98095_02F_DAI1_LVL1 0x2F +#define M98095_030_DAI1_LVL2 0x30 +#define M98095_031_DAI2_CLKMODE 0x31 +#define M98095_032_DAI2_CLKCFG_HI 0x32 +#define M98095_033_DAI2_CLKCFG_LO 0x33 +#define M98095_034_DAI2_FORMAT 0x34 +#define M98095_035_DAI2_CLOCK 0x35 +#define M98095_036_DAI2_IOCFG 0x36 +#define M98095_037_DAI2_TDM 0x37 +#define M98095_038_DAI2_FILTERS 0x38 +#define M98095_039_DAI2_LVL1 0x39 +#define M98095_03A_DAI2_LVL2 0x3A +#define M98095_03B_DAI3_CLKMODE 0x3B +#define M98095_03C_DAI3_CLKCFG_HI 0x3C +#define M98095_03D_DAI3_CLKCFG_LO 0x3D +#define M98095_03E_DAI3_FORMAT 0x3E +#define M98095_03F_DAI3_CLOCK 0x3F +#define M98095_040_DAI3_IOCFG 0x40 +#define M98095_041_DAI3_TDM 0x41 +#define M98095_042_DAI3_FILTERS 0x42 +#define M98095_043_DAI3_LVL1 0x43 +#define M98095_044_DAI3_LVL2 0x44 +#define M98095_045_CFG_DSP 0x45 +#define M98095_046_DAC_CTRL1 0x46 +#define M98095_047_DAC_CTRL2 0x47 +#define M98095_048_MIX_DAC_LR 0x48 +#define M98095_049_MIX_DAC_M 0x49 +#define M98095_04A_MIX_ADC_LEFT 0x4A +#define M98095_04B_MIX_ADC_RIGHT 0x4B +#define M98095_04C_MIX_HP_LEFT 0x4C +#define M98095_04D_MIX_HP_RIGHT 0x4D +#define M98095_04E_CFG_HP 0x4E +#define M98095_04F_MIX_RCV 0x4F +#define M98095_050_MIX_SPK_LEFT 0x50 +#define M98095_051_MIX_SPK_RIGHT 0x51 +#define M98095_052_MIX_SPK_CFG 0x52 +#define M98095_053_MIX_LINEOUT1 0x53 +#define M98095_054_MIX_LINEOUT2 0x54 +#define M98095_055_MIX_LINEOUT_CFG 0x55 +#define M98095_056_LVL_SIDETONE_DAI12 0x56 +#define M98095_057_LVL_SIDETONE_DAI3 0x57 +#define M98095_058_LVL_DAI1_PLAY 0x58 +#define M98095_059_LVL_DAI1_EQ 0x59 +#define M98095_05A_LVL_DAI2_PLAY 0x5A +#define M98095_05B_LVL_DAI2_EQ 0x5B +#define M98095_05C_LVL_DAI3_PLAY 0x5C +#define M98095_05D_LVL_ADC_L 0x5D +#define M98095_05E_LVL_ADC_R 0x5E +#define M98095_05F_LVL_MIC1 0x5F +#define M98095_060_LVL_MIC2 0x60 +#define M98095_061_LVL_LINEIN 0x61 +#define M98095_062_LVL_LINEOUT1 0x62 +#define M98095_063_LVL_LINEOUT2 0x63 +#define M98095_064_LVL_HP_L 0x64 +#define M98095_065_LVL_HP_R 0x65 +#define M98095_066_LVL_RCV 0x66 +#define M98095_067_LVL_SPK_L 0x67 +#define M98095_068_LVL_SPK_R 0x68 +#define M98095_069_MICAGC_CFG 0x69 +#define M98095_06A_MICAGC_THRESH 0x6A +#define M98095_06B_SPK_NOISEGATE 0x6B +#define M98095_06C_DAI1_ALC1_TIME 0x6C +#define M98095_06D_DAI1_ALC1_COMP 0x6D +#define M98095_06E_DAI1_ALC1_EXPN 0x6E +#define M98095_06F_DAI1_ALC1_GAIN 0x6F +#define M98095_070_DAI1_ALC2_TIME 0x70 +#define M98095_071_DAI1_ALC2_COMP 0x71 +#define M98095_072_DAI1_ALC2_EXPN 0x72 +#define M98095_073_DAI1_ALC2_GAIN 0x73 +#define M98095_074_DAI1_ALC3_TIME 0x74 +#define M98095_075_DAI1_ALC3_COMP 0x75 +#define M98095_076_DAI1_ALC3_EXPN 0x76 +#define M98095_077_DAI1_ALC3_GAIN 0x77 +#define M98095_078_DAI2_ALC1_TIME 0x78 +#define M98095_079_DAI2_ALC1_COMP 0x79 +#define M98095_07A_DAI2_ALC1_EXPN 0x7A +#define M98095_07B_DAI2_ALC1_GAIN 0x7B +#define M98095_07C_DAI2_ALC2_TIME 0x7C +#define M98095_07D_DAI2_ALC2_COMP 0x7D +#define M98095_07E_DAI2_ALC2_EXPN 0x7E +#define M98095_07F_DAI2_ALC2_GAIN 0x7F +#define M98095_080_DAI2_ALC3_TIME 0x80 +#define M98095_081_DAI2_ALC3_COMP 0x81 +#define M98095_082_DAI2_ALC3_EXPN 0x82 +#define M98095_083_DAI2_ALC3_GAIN 0x83 +#define M98095_084_HP_NOISE_GATE 0x84 +#define M98095_085_AUX_ADC 0x85 +#define M98095_086_CFG_LINE 0x86 +#define M98095_087_CFG_MIC 0x87 +#define M98095_088_CFG_LEVEL 0x88 +#define M98095_089_JACK_DET_AUTO 0x89 +#define M98095_08A_JACK_DET_MANUAL 0x8A +#define M98095_08B_JACK_KEYSCAN_DBC 0x8B +#define M98095_08C_JACK_KEYSCAN_DLY 0x8C +#define M98095_08D_JACK_KEY_THRESH 0x8D +#define M98095_08E_JACK_DC_SLEW 0x8E +#define M98095_08F_JACK_TEST_CFG 0x8F +#define M98095_090_PWR_EN_IN 0x90 +#define M98095_091_PWR_EN_OUT 0x91 +#define M98095_092_PWR_EN_OUT 0x92 +#define M98095_093_BIAS_CTRL 0x93 +#define M98095_094_PWR_DAC_21 0x94 +#define M98095_095_PWR_DAC_03 0x95 +#define M98095_096_PWR_DAC_CK 0x96 +#define M98095_097_PWR_SYS 0x97 + +#define M98095_0FF_REV_ID 0xFF + +#define M98095_REG_CNT (0xFF+1) +#define M98095_REG_MAX_CACHED 0X97 + +/* MAX98095 Registers Bit Fields */ + +/* M98095_00F_HOST_CFG */ +#define M98095_SEG (1<<0) +#define M98095_XTEN (1<<1) +#define M98095_MDLLEN (1<<2) + +/* M98095_027_DAI1_CLKMODE, M98095_031_DAI2_CLKMODE, M98095_03B_DAI3_CLKMODE */ +#define M98095_CLKMODE_MASK 0xFF + +/* M98095_02A_DAI1_FORMAT, M98095_034_DAI2_FORMAT, M98095_03E_DAI3_FORMAT */ +#define M98095_DAI_MAS (1<<7) +#define M98095_DAI_WCI (1<<6) +#define M98095_DAI_BCI (1<<5) +#define M98095_DAI_DLY (1<<4) +#define M98095_DAI_TDM (1<<2) +#define M98095_DAI_FSW (1<<1) +#define M98095_DAI_WS (1<<0) + +/* M98095_02B_DAI1_CLOCK, M98095_035_DAI2_CLOCK, M98095_03F_DAI3_CLOCK */ +#define M98095_DAI_BSEL64 (1<<0) +#define M98095_DAI_DOSR_DIV2 (0<<5) +#define M98095_DAI_DOSR_DIV4 (1<<5) + +/* M98095_02C_DAI1_IOCFG, M98095_036_DAI2_IOCFG, M98095_040_DAI3_IOCFG */ +#define M98095_S1NORMAL (1<<6) +#define M98095_S2NORMAL (2<<6) +#define M98095_S3NORMAL (3<<6) +#define M98095_SDATA (3<<0) + +/* M98095_02E_DAI1_FILTERS, M98095_038_DAI2_FILTERS, M98095_042_DAI3_FILTERS */ +#define M98095_DAI_DHF (1<<3) + +/* M98095_045_DSP_CFG */ +#define M98095_DSPNORMAL (5<<4) + +/* M98095_048_MIX_DAC_LR */ +#define M98095_DAI1L_TO_DACR (1<<7) +#define M98095_DAI1R_TO_DACR (1<<6) +#define M98095_DAI2M_TO_DACR (1<<5) +#define M98095_DAI1L_TO_DACL (1<<3) +#define M98095_DAI1R_TO_DACL (1<<2) +#define M98095_DAI2M_TO_DACL (1<<1) +#define M98095_DAI3M_TO_DACL (1<<0) + +/* M98095_049_MIX_DAC_M */ +#define M98095_DAI1L_TO_DACM (1<<3) +#define M98095_DAI1R_TO_DACM (1<<2) +#define M98095_DAI2M_TO_DACM (1<<1) +#define M98095_DAI3M_TO_DACM (1<<0) + +/* M98095_04E_MIX_HP_CFG */ +#define M98095_HPNORMAL (3<<4) + +/* M98095_05F_LVL_MIC1, M98095_060_LVL_MIC2 */ +#define M98095_MICPRE_MASK (3<<5) +#define M98095_MICPRE_SHIFT 5 + +/* M98095_064_LVL_HP_L, M98095_065_LVL_HP_R */ +#define M98095_HP_MUTE (1<<7) + +/* M98095_066_LVL_RCV */ +#define M98095_REC_MUTE (1<<7) + +/* M98095_067_LVL_SPK_L, M98095_068_LVL_SPK_R */ +#define M98095_SP_MUTE (1<<7) + +/* M98095_087_CFG_MIC */ +#define M98095_MICSEL_MASK (3<<0) +#define M98095_DIGMIC_L (1<<2) +#define M98095_DIGMIC_R (1<<3) +#define M98095_DIGMIC2L (1<<4) +#define M98095_DIGMIC2R (1<<5) + +/* M98095_088_CFG_LEVEL */ +#define M98095_VSEN (1<<6) +#define M98095_ZDEN (1<<5) +#define M98095_BQ2EN (1<<3) +#define M98095_BQ1EN (1<<2) +#define M98095_EQ2EN (1<<1) +#define M98095_EQ1EN (1<<0) + +/* M98095_090_PWR_EN_IN */ +#define M98095_INEN (1<<7) +#define M98095_MB2EN (1<<3) +#define M98095_MB1EN (1<<2) +#define M98095_MBEN (3<<2) +#define M98095_ADREN (1<<1) +#define M98095_ADLEN (1<<0) + +/* M98095_091_PWR_EN_OUT */ +#define M98095_HPLEN (1<<7) +#define M98095_HPREN (1<<6) +#define M98095_SPLEN (1<<5) +#define M98095_SPREN (1<<4) +#define M98095_RECEN (1<<3) +#define M98095_DALEN (1<<1) +#define M98095_DAREN (1<<0) + +/* M98095_092_PWR_EN_OUT */ +#define M98095_SPK_FIXEDSPECTRUM (0<<4) +#define M98095_SPK_SPREADSPECTRUM (1<<4) + +/* M98095_097_PWR_SYS */ +#define M98095_SHDNRUN (1<<7) +#define M98095_PERFMODE (1<<3) +#define M98095_HPPLYBACK (1<<2) +#define M98095_PWRSV8K (1<<1) +#define M98095_PWRSV (1<<0) + +#define M98095_COEFS_PER_BAND 5 + +/* Equalizer filter coefficients */ +#define M98095_110_DAI1_EQ_BASE 0x10 +#define M98095_142_DAI2_EQ_BASE 0x42 + +/* Biquad filter coefficients */ +#define M98095_174_DAI1_BQ_BASE 0x74 +#define M98095_17E_DAI2_BQ_BASE 0x7E + +/* function prototype */ + +/* + * intialise max98095 sound codec device for the given configuration + * + * @param blob FDT node for codec values + * @param sampling_rate Sampling rate (Hz) + * @param mclk_freq MCLK Frequency (Hz) + * @param bits_per_sample bits per Sample (must be 16 or 24) + * + * @returns -1 for error and 0 Success. + */ +int max98095_init(const void *blob, int sampling_rate, int mclk_freq, + int bits_per_sample); + +#endif diff --git a/drivers/sound/sound.c b/drivers/sound/sound.c index fa8432d..a4bf4ad 100644 --- a/drivers/sound/sound.c +++ b/drivers/sound/sound.c @@ -31,6 +31,7 @@ #include <sound.h> #include <asm/arch/sound.h> #include "wm8994.h" +#include "max98095.h" /* defines */ #define SOUND_400_HZ 400 @@ -149,11 +150,15 @@ static int codec_init(const void *blob, struct i2stx_info *pi2s_tx) pi2s_tx->samplingrate, (pi2s_tx->samplingrate * (pi2s_tx->rfs)), pi2s_tx->bitspersample, pi2s_tx->channels); + } else if (!strcmp(codectype, "max98095")) { + ret = max98095_init(blob, pi2s_tx->samplingrate, + (pi2s_tx->samplingrate * (pi2s_tx->rfs)), + pi2s_tx->bitspersample); } else { - debug("%s: Unknown code type %s\n", __func__, - codectype); + debug("%s: Unknown codec type %s\n", __func__, codectype); return -1; } + if (ret) { debug("%s: Codec init failed\n", __func__); return -1; diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index b8264df..d08609e 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -25,6 +25,9 @@ include $(TOPDIR)/config.mk LIB := $(obj)libspi.o +# There are many options which enable SPI, so make this library available +COBJS-y += spi.o + COBJS-$(CONFIG_ALTERA_SPI) += altera_spi.o COBJS-$(CONFIG_ANDES_SPI) += andes_spi.o COBJS-$(CONFIG_ARMADA100_SPI) += armada100_spi.o @@ -36,6 +39,7 @@ COBJS-$(CONFIG_CF_SPI) += cf_spi.o COBJS-$(CONFIG_CF_QSPI) += cf_qspi.o COBJS-$(CONFIG_DAVINCI_SPI) += davinci_spi.o COBJS-$(CONFIG_EXYNOS_SPI) += exynos_spi.o +COBJS-$(CONFIG_ICH_SPI) += ich.o COBJS-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o COBJS-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o COBJS-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o @@ -46,8 +50,10 @@ COBJS-$(CONFIG_OMAP3_SPI) += omap3_spi.o COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o COBJS-$(CONFIG_SH_SPI) += sh_spi.o COBJS-$(CONFIG_FSL_ESPI) += fsl_espi.o -COBJS-$(CONFIG_TEGRA_SPI) += tegra_spi.o -COBJS-$(CONFIG_TEGRA_SLINK) += tegra_slink.o +COBJS-$(CONFIG_FDT_SPI) += fdt_spi.o +COBJS-$(CONFIG_TEGRA20_SFLASH) += tegra20_sflash.o +COBJS-$(CONFIG_TEGRA20_SLINK) += tegra20_slink.o +COBJS-$(CONFIG_TEGRA114_SPI) += tegra114_spi.o COBJS-$(CONFIG_XILINX_SPI) += xilinx_spi.o COBJS := $(COBJS-y) diff --git a/drivers/spi/altera_spi.c b/drivers/spi/altera_spi.c index 138d6f4..b53607a 100644 --- a/drivers/spi/altera_spi.c +++ b/drivers/spi/altera_spi.c @@ -83,12 +83,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, if (!spi_cs_is_valid(bus, cs)) return NULL; - altspi = malloc(sizeof(*altspi)); + altspi = spi_alloc_slave(struct altera_spi_slave, bus, cs); if (!altspi) return NULL; - altspi->slave.bus = bus; - altspi->slave.cs = cs; altspi->base = altera_spi_base_list[bus]; debug("%s: bus:%i cs:%i base:%lx\n", __func__, bus, cs, altspi->base); diff --git a/drivers/spi/andes_spi.c b/drivers/spi/andes_spi.c index fdde139..c56377b 100644 --- a/drivers/spi/andes_spi.c +++ b/drivers/spi/andes_spi.c @@ -53,12 +53,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, if (!spi_cs_is_valid(bus, cs)) return NULL; - ds = malloc(sizeof(*ds)); + ds = spi_alloc_slave(struct andes_spi_slave, bus, cs); if (!ds) return NULL; - ds->slave.bus = bus; - ds->slave.cs = cs; ds->regs = (struct andes_spi_regs *)CONFIG_SYS_SPI_BASE; /* diff --git a/drivers/spi/armada100_spi.c b/drivers/spi/armada100_spi.c index 7384c9c..afdbe05 100644 --- a/drivers/spi/armada100_spi.c +++ b/drivers/spi/armada100_spi.c @@ -120,12 +120,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, { struct armd_spi_slave *pss; - pss = malloc(sizeof(*pss)); + pss = spi_alloc_slave(struct armd_spi_slave, bus, cs); if (!pss) return NULL; - pss->slave.bus = bus; - pss->slave.cs = cs; pss->spi_reg = (struct ssp_reg *)SSP_REG_BASE(CONFIG_SYS_SSP_PORT); pss->cr0 = SSCR0_MOTO | SSCR0_DATASIZE(DEFAULT_WORD_LEN) | SSCR0_SSE; diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index ce7d460..f4b1bad 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c @@ -84,12 +84,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, if (mode & SPI_CPOL) csrx |= ATMEL_SPI_CSRx_CPOL; - as = malloc(sizeof(struct atmel_spi_slave)); + as = spi_alloc_slave(struct atmel_spi_slave, bus, cs); if (!as) return NULL; - as->slave.bus = bus; - as->slave.cs = cs; as->regs = regs; as->mr = ATMEL_SPI_MR_MSTR | ATMEL_SPI_MR_MODFDIS #if defined(CONFIG_AT91SAM9X5) || defined(CONFIG_AT91SAM9M10G45) diff --git a/drivers/spi/bfin_spi.c b/drivers/spi/bfin_spi.c index e080bec..ab2e8b9 100644 --- a/drivers/spi/bfin_spi.c +++ b/drivers/spi/bfin_spi.c @@ -182,12 +182,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, default: return NULL; } - bss = malloc(sizeof(*bss)); + bss = spi_alloc_slave(struct bfin_spi_slave, bus, cs); if (!bss) return NULL; - bss->slave.bus = bus; - bss->slave.cs = cs; bss->mmr_base = (void *)mmr_base; bss->ctl = SPE | MSTR | TDBR_CORE; if (mode & SPI_CPHA) bss->ctl |= CPHA; diff --git a/drivers/spi/bfin_spi6xx.c b/drivers/spi/bfin_spi6xx.c index fde3447..c25c4a9 100644 --- a/drivers/spi/bfin_spi6xx.c +++ b/drivers/spi/bfin_spi6xx.c @@ -178,12 +178,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, return NULL; } - bss = malloc(sizeof(*bss)); + bss = spi_alloc_slave(struct bfin_spi_slave, bus, cs); if (!bss) return NULL; - bss->slave.bus = bus; - bss->slave.cs = cs; bss->regs = (struct bfin_spi_regs *)reg_base; bss->control = SPI_CTL_EN | SPI_CTL_MSTR; if (mode & SPI_CPHA) diff --git a/drivers/spi/cf_qspi.c b/drivers/spi/cf_qspi.c index 72dd1a5..a37ac4e 100644 --- a/drivers/spi/cf_qspi.c +++ b/drivers/spi/cf_qspi.c @@ -120,13 +120,11 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, if (!spi_cs_is_valid(bus, cs)) return NULL; - dev = malloc(sizeof(struct cf_qspi_slave)); + dev = spi_alloc_slave(struct cf_qspi_slave, bus, cs); if (!dev) return NULL; /* Initialize to known value */ - dev->slave.bus = bus; - dev->slave.cs = cs; dev->regs = (qspi_t *)MMAP_QSPI; dev->qmr = 0; dev->qwr = 0; diff --git a/drivers/spi/cf_spi.c b/drivers/spi/cf_spi.c index a883da9..afe7917 100644 --- a/drivers/spi/cf_spi.c +++ b/drivers/spi/cf_spi.c @@ -330,12 +330,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, if (!spi_cs_is_valid(bus, cs)) return NULL; - cfslave = malloc(sizeof(struct cf_spi_slave)); + cfslave = spi_alloc_slave(struct cf_spi_slave, bus, cs); if (!cfslave) return NULL; - cfslave->slave.bus = bus; - cfslave->slave.cs = cs; cfslave->baudrate = max_hz; /* specific setup */ diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 13aca52..74792af 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -44,12 +44,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, if (!spi_cs_is_valid(bus, cs)) return NULL; - ds = malloc(sizeof(*ds)); + ds = spi_alloc_slave(struct davinci_spi_slave, bus, cs); if (!ds) return NULL; - ds->slave.bus = bus; - ds->slave.cs = cs; ds->regs = (struct davinci_spi_regs *)CONFIG_SYS_SPI_BASE; ds->freq = max_hz; diff --git a/drivers/spi/exynos_spi.c b/drivers/spi/exynos_spi.c index be60ada..607e1cd 100644 --- a/drivers/spi/exynos_spi.c +++ b/drivers/spi/exynos_spi.c @@ -89,15 +89,13 @@ struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs, return NULL; } - spi_slave = malloc(sizeof(*spi_slave)); + spi_slave = spi_alloc_slave(struct exynos_spi_slave, busnum, cs); if (!spi_slave) { debug("%s: Could not allocate spi_slave\n", __func__); return NULL; } bus = &spi_bus[busnum]; - spi_slave->slave.bus = busnum; - spi_slave->slave.cs = cs; spi_slave->regs = bus->regs; spi_slave->mode = mode; spi_slave->periph_id = bus->periph_id; @@ -360,6 +358,7 @@ static inline struct exynos_spi *get_spi_base(int dev_index) * @param bus SPI bus structure to fill with information * @return 0 if ok, or -FDT_ERR_NOTFOUND if something was missing */ +#ifdef CONFIG_OF_CONTROL static int spi_get_config(const void *blob, int node, struct spi_bus *bus) { bus->node = node; @@ -415,6 +414,7 @@ static int process_nodes(const void *blob, int node_list[], int count) return 0; } +#endif /* Sadly there is no error return from this function */ void spi_init(void) diff --git a/drivers/spi/fdt_spi.c b/drivers/spi/fdt_spi.c new file mode 100644 index 0000000..58f139a --- /dev/null +++ b/drivers/spi/fdt_spi.c @@ -0,0 +1,186 @@ +/* + * Common fdt based SPI driver front end + * + * Copyright (c) 2013 NVIDIA Corporation + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <malloc.h> +#include <asm/io.h> +#include <asm/gpio.h> +#include <asm/arch/clock.h> +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch-tegra20/tegra20_sflash.h> +#include <asm/arch-tegra20/tegra20_slink.h> +#include <asm/arch-tegra114/tegra114_spi.h> +#include <spi.h> +#include <fdtdec.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct fdt_spi_driver { + int compat; + int max_ctrls; + int (*init)(int *node_list, int count); + int (*claim_bus)(struct spi_slave *slave); + int (*release_bus)(struct spi_slave *slave); + int (*cs_is_valid)(unsigned int bus, unsigned int cs); + struct spi_slave *(*setup_slave)(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode); + void (*free_slave)(struct spi_slave *slave); + void (*cs_activate)(struct spi_slave *slave); + void (*cs_deactivate)(struct spi_slave *slave); + int (*xfer)(struct spi_slave *slave, unsigned int bitlen, + const void *data_out, void *data_in, unsigned long flags); +}; + +static struct fdt_spi_driver fdt_spi_drivers[] = { +#ifdef CONFIG_TEGRA20_SFLASH + { + .compat = COMPAT_NVIDIA_TEGRA20_SFLASH, + .max_ctrls = 1, + .init = tegra20_spi_init, + .claim_bus = tegra20_spi_claim_bus, + .cs_is_valid = tegra20_spi_cs_is_valid, + .setup_slave = tegra20_spi_setup_slave, + .free_slave = tegra20_spi_free_slave, + .cs_activate = tegra20_spi_cs_activate, + .cs_deactivate = tegra20_spi_cs_deactivate, + .xfer = tegra20_spi_xfer, + }, +#endif +#ifdef CONFIG_TEGRA20_SLINK + { + .compat = COMPAT_NVIDIA_TEGRA20_SLINK, + .max_ctrls = CONFIG_TEGRA_SLINK_CTRLS, + .init = tegra30_spi_init, + .claim_bus = tegra30_spi_claim_bus, + .cs_is_valid = tegra30_spi_cs_is_valid, + .setup_slave = tegra30_spi_setup_slave, + .free_slave = tegra30_spi_free_slave, + .cs_activate = tegra30_spi_cs_activate, + .cs_deactivate = tegra30_spi_cs_deactivate, + .xfer = tegra30_spi_xfer, + }, +#endif +#ifdef CONFIG_TEGRA114_SPI + { + .compat = COMPAT_NVIDIA_TEGRA114_SPI, + .max_ctrls = CONFIG_TEGRA114_SPI_CTRLS, + .init = tegra114_spi_init, + .claim_bus = tegra114_spi_claim_bus, + .cs_is_valid = tegra114_spi_cs_is_valid, + .setup_slave = tegra114_spi_setup_slave, + .free_slave = tegra114_spi_free_slave, + .cs_activate = tegra114_spi_cs_activate, + .cs_deactivate = tegra114_spi_cs_deactivate, + .xfer = tegra114_spi_xfer, + }, +#endif +}; + +static struct fdt_spi_driver *driver; + +int spi_cs_is_valid(unsigned int bus, unsigned int cs) +{ + if (!driver) + return 0; + else if (!driver->cs_is_valid) + return 1; + else + return driver->cs_is_valid(bus, cs); +} + +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode) +{ + if (!driver || !driver->setup_slave) + return NULL; + + return driver->setup_slave(bus, cs, max_hz, mode); +} + +void spi_free_slave(struct spi_slave *slave) +{ + if (driver && driver->free_slave) + return driver->free_slave(slave); +} + +static int spi_init_driver(struct fdt_spi_driver *driver) +{ + int count; + int node_list[driver->max_ctrls]; + + count = fdtdec_find_aliases_for_id(gd->fdt_blob, "spi", + driver->compat, + node_list, + driver->max_ctrls); + return driver->init(node_list, count); +} + +void spi_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(fdt_spi_drivers); i++) { + driver = &fdt_spi_drivers[i]; + if (!spi_init_driver(driver)) + break; + } + if (i == ARRAY_SIZE(fdt_spi_drivers)) + driver = NULL; +} + +int spi_claim_bus(struct spi_slave *slave) +{ + if (!driver) + return 1; + if (!driver->claim_bus) + return 0; + + return driver->claim_bus(slave); +} + +void spi_release_bus(struct spi_slave *slave) +{ + if (driver && driver->release_bus) + driver->release_bus(slave); +} + +void spi_cs_activate(struct spi_slave *slave) +{ + if (driver && driver->cs_activate) + driver->cs_activate(slave); +} + +void spi_cs_deactivate(struct spi_slave *slave) +{ + if (driver && driver->cs_deactivate) + driver->cs_deactivate(slave); +} + +int spi_xfer(struct spi_slave *slave, unsigned int bitlen, + const void *data_out, void *data_in, unsigned long flags) +{ + if (!driver || !driver->xfer) + return -1; + + return driver->xfer(slave, bitlen, data_out, data_in, flags); +} diff --git a/drivers/spi/fsl_espi.c b/drivers/spi/fsl_espi.c index eb99e90..28609ee 100644 --- a/drivers/spi/fsl_espi.c +++ b/drivers/spi/fsl_espi.c @@ -79,12 +79,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, if (!spi_cs_is_valid(bus, cs)) return NULL; - fsl = malloc(sizeof(struct fsl_spi_slave)); + fsl = spi_alloc_slave(struct fsl_spi_slave, bus, cs); if (!fsl) return NULL; - fsl->slave.bus = bus; - fsl->slave.cs = cs; fsl->mode = mode; fsl->max_transfer_length = ESPI_MAX_DATA_TRANSFER_LEN; diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c new file mode 100644 index 0000000..468d356 --- /dev/null +++ b/drivers/spi/ich.c @@ -0,0 +1,754 @@ +/* + * Copyright (c) 2011-12 The Chromium OS Authors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * This file is derived from the flashrom project. + */ + +#include <common.h> +#include <malloc.h> +#include <spi.h> +#include <pci.h> +#include <pci_ids.h> +#include <asm/io.h> + +#include "ich.h" + +#define SPI_OPCODE_WREN 0x06 +#define SPI_OPCODE_FAST_READ 0x0b + +struct ich_ctlr { + pci_dev_t dev; /* PCI device number */ + int ich_version; /* Controller version, 7 or 9 */ + int ichspi_lock; + int locked; + uint8_t *opmenu; + int menubytes; + void *base; /* Base of register set */ + uint16_t *preop; + uint16_t *optype; + uint32_t *addr; + uint8_t *data; + unsigned databytes; + uint8_t *status; + uint16_t *control; + uint32_t *bbar; + uint32_t *pr; /* only for ich9 */ + uint8_t *speed; /* pointer to speed control */ + ulong max_speed; /* Maximum bus speed in MHz */ +}; + +struct ich_ctlr ctlr; + +static inline struct ich_spi_slave *to_ich_spi(struct spi_slave *slave) +{ + return container_of(slave, struct ich_spi_slave, slave); +} + +static unsigned int ich_reg(const void *addr) +{ + return (unsigned)(addr - ctlr.base) & 0xffff; +} + +static u8 ich_readb(const void *addr) +{ + u8 value = readb(addr); + + debug("read %2.2x from %4.4x\n", value, ich_reg(addr)); + + return value; +} + +static u16 ich_readw(const void *addr) +{ + u16 value = readw(addr); + + debug("read %4.4x from %4.4x\n", value, ich_reg(addr)); + + return value; +} + +static u32 ich_readl(const void *addr) +{ + u32 value = readl(addr); + + debug("read %8.8x from %4.4x\n", value, ich_reg(addr)); + + return value; +} + +static void ich_writeb(u8 value, void *addr) +{ + writeb(value, addr); + debug("wrote %2.2x to %4.4x\n", value, ich_reg(addr)); +} + +static void ich_writew(u16 value, void *addr) +{ + writew(value, addr); + debug("wrote %4.4x to %4.4x\n", value, ich_reg(addr)); +} + +static void ich_writel(u32 value, void *addr) +{ + writel(value, addr); + debug("wrote %8.8x to %4.4x\n", value, ich_reg(addr)); +} + +static void write_reg(const void *value, void *dest, uint32_t size) +{ + memcpy_toio(dest, value, size); +} + +static void read_reg(const void *src, void *value, uint32_t size) +{ + memcpy_fromio(value, src, size); +} + +static void ich_set_bbar(struct ich_ctlr *ctlr, uint32_t minaddr) +{ + const uint32_t bbar_mask = 0x00ffff00; + uint32_t ichspi_bbar; + + minaddr &= bbar_mask; + ichspi_bbar = ich_readl(ctlr->bbar) & ~bbar_mask; + ichspi_bbar |= minaddr; + ich_writel(ichspi_bbar, ctlr->bbar); +} + +int spi_cs_is_valid(unsigned int bus, unsigned int cs) +{ + puts("spi_cs_is_valid used but not implemented\n"); + return 0; +} + +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode) +{ + struct ich_spi_slave *ich; + + ich = spi_alloc_slave(struct ich_spi_slave, bus, cs); + if (!ich) { + puts("ICH SPI: Out of memory\n"); + return NULL; + } + + /* + * Yes this controller can only write a small number of bytes at + * once! The limit is typically 64 bytes. + */ + ich->slave.max_write_size = ctlr.databytes; + ich->speed = max_hz; + + return &ich->slave; +} + +void spi_free_slave(struct spi_slave *slave) +{ + struct ich_spi_slave *ich = to_ich_spi(slave); + + free(ich); +} + +/* + * Check if this device ID matches one of supported Intel PCH devices. + * + * Return the ICH version if there is a match, or zero otherwise. + */ +static int get_ich_version(uint16_t device_id) +{ + if (device_id == PCI_DEVICE_ID_INTEL_TGP_LPC) + return 7; + + if ((device_id >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN && + device_id <= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX) || + (device_id >= PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MIN && + device_id <= PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX)) + return 9; + + return 0; +} + +/* @return 1 if the SPI flash supports the 33MHz speed */ +static int ich9_can_do_33mhz(pci_dev_t dev) +{ + u32 fdod, speed; + + /* Observe SPI Descriptor Component Section 0 */ + pci_write_config_dword(dev, 0xb0, 0x1000); + + /* Extract the Write/Erase SPI Frequency from descriptor */ + pci_read_config_dword(dev, 0xb4, &fdod); + + /* Bits 23:21 have the fast read clock frequency, 0=20MHz, 1=33MHz */ + speed = (fdod >> 21) & 7; + + return speed == 1; +} + +static int ich_find_spi_controller(pci_dev_t *devp, int *ich_versionp) +{ + int last_bus = pci_last_busno(); + int bus; + + if (last_bus == -1) { + debug("No PCI busses?\n"); + return -1; + } + + for (bus = 0; bus <= last_bus; bus++) { + uint16_t vendor_id, device_id; + uint32_t ids; + pci_dev_t dev; + + dev = PCI_BDF(bus, 31, 0); + pci_read_config_dword(dev, 0, &ids); + vendor_id = ids; + device_id = ids >> 16; + + if (vendor_id == PCI_VENDOR_ID_INTEL) { + *devp = dev; + *ich_versionp = get_ich_version(device_id); + return 0; + } + } + + debug("ICH SPI: No ICH found.\n"); + return -1; +} + +static int ich_init_controller(struct ich_ctlr *ctlr) +{ + uint8_t *rcrb; /* Root Complex Register Block */ + uint32_t rcba; /* Root Complex Base Address */ + + pci_read_config_dword(ctlr->dev, 0xf0, &rcba); + /* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable. */ + rcrb = (uint8_t *)(rcba & 0xffffc000); + if (ctlr->ich_version == 7) { + struct ich7_spi_regs *ich7_spi; + + ich7_spi = (struct ich7_spi_regs *)(rcrb + 0x3020); + ctlr->ichspi_lock = ich_readw(&ich7_spi->spis) & SPIS_LOCK; + ctlr->opmenu = ich7_spi->opmenu; + ctlr->menubytes = sizeof(ich7_spi->opmenu); + ctlr->optype = &ich7_spi->optype; + ctlr->addr = &ich7_spi->spia; + ctlr->data = (uint8_t *)ich7_spi->spid; + ctlr->databytes = sizeof(ich7_spi->spid); + ctlr->status = (uint8_t *)&ich7_spi->spis; + ctlr->control = &ich7_spi->spic; + ctlr->bbar = &ich7_spi->bbar; + ctlr->preop = &ich7_spi->preop; + ctlr->base = ich7_spi; + } else if (ctlr->ich_version == 9) { + struct ich9_spi_regs *ich9_spi; + + ich9_spi = (struct ich9_spi_regs *)(rcrb + 0x3800); + ctlr->ichspi_lock = ich_readw(&ich9_spi->hsfs) & HSFS_FLOCKDN; + ctlr->opmenu = ich9_spi->opmenu; + ctlr->menubytes = sizeof(ich9_spi->opmenu); + ctlr->optype = &ich9_spi->optype; + ctlr->addr = &ich9_spi->faddr; + ctlr->data = (uint8_t *)ich9_spi->fdata; + ctlr->databytes = sizeof(ich9_spi->fdata); + ctlr->status = &ich9_spi->ssfs; + ctlr->control = (uint16_t *)ich9_spi->ssfc; + ctlr->speed = ich9_spi->ssfc + 2; + ctlr->bbar = &ich9_spi->bbar; + ctlr->preop = &ich9_spi->preop; + ctlr->pr = &ich9_spi->pr[0]; + ctlr->base = ich9_spi; + } else { + debug("ICH SPI: Unrecognized ICH version %d.\n", + ctlr->ich_version); + return -1; + } + debug("ICH SPI: Version %d detected\n", ctlr->ich_version); + + /* Work out the maximum speed we can support */ + ctlr->max_speed = 20000000; + if (ctlr->ich_version == 9 && ich9_can_do_33mhz(ctlr->dev)) + ctlr->max_speed = 33000000; + + ich_set_bbar(ctlr, 0); + + return 0; +} + +void spi_init(void) +{ + uint8_t bios_cntl; + + if (ich_find_spi_controller(&ctlr.dev, &ctlr.ich_version)) { + printf("ICH SPI: Cannot find device\n"); + return; + } + + if (ich_init_controller(&ctlr)) { + printf("ICH SPI: Cannot setup controller\n"); + return; + } + + /* + * Disable the BIOS write protect so write commands are allowed. On + * v9, deassert SMM BIOS Write Protect Disable. + */ + pci_read_config_byte(ctlr.dev, 0xdc, &bios_cntl); + if (ctlr.ich_version == 9) + bios_cntl &= ~(1 << 5); + pci_write_config_byte(ctlr.dev, 0xdc, bios_cntl | 0x1); +} + +int spi_claim_bus(struct spi_slave *slave) +{ + /* Handled by ICH automatically. */ + return 0; +} + +void spi_release_bus(struct spi_slave *slave) +{ + /* Handled by ICH automatically. */ +} + +void spi_cs_activate(struct spi_slave *slave) +{ + /* Handled by ICH automatically. */ +} + +void spi_cs_deactivate(struct spi_slave *slave) +{ + /* Handled by ICH automatically. */ +} + +static inline void spi_use_out(struct spi_trans *trans, unsigned bytes) +{ + trans->out += bytes; + trans->bytesout -= bytes; +} + +static inline void spi_use_in(struct spi_trans *trans, unsigned bytes) +{ + trans->in += bytes; + trans->bytesin -= bytes; +} + +static void spi_setup_type(struct spi_trans *trans, int data_bytes) +{ + trans->type = 0xFF; + + /* Try to guess spi type from read/write sizes. */ + if (trans->bytesin == 0) { + if (trans->bytesout + data_bytes > 4) + /* + * If bytesin = 0 and bytesout > 4, we presume this is + * a write data operation, which is accompanied by an + * address. + */ + trans->type = SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS; + else + trans->type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS; + return; + } + + if (trans->bytesout == 1) { /* and bytesin is > 0 */ + trans->type = SPI_OPCODE_TYPE_READ_NO_ADDRESS; + return; + } + + if (trans->bytesout == 4) /* and bytesin is > 0 */ + trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS; + + /* Fast read command is called with 5 bytes instead of 4 */ + if (trans->out[0] == SPI_OPCODE_FAST_READ && trans->bytesout == 5) { + trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS; + --trans->bytesout; + } +} + +static int spi_setup_opcode(struct spi_trans *trans) +{ + uint16_t optypes; + uint8_t opmenu[ctlr.menubytes]; + + trans->opcode = trans->out[0]; + spi_use_out(trans, 1); + if (!ctlr.ichspi_lock) { + /* The lock is off, so just use index 0. */ + ich_writeb(trans->opcode, ctlr.opmenu); + optypes = ich_readw(ctlr.optype); + optypes = (optypes & 0xfffc) | (trans->type & 0x3); + ich_writew(optypes, ctlr.optype); + return 0; + } else { + /* The lock is on. See if what we need is on the menu. */ + uint8_t optype; + uint16_t opcode_index; + + /* Write Enable is handled as atomic prefix */ + if (trans->opcode == SPI_OPCODE_WREN) + return 0; + + read_reg(ctlr.opmenu, opmenu, sizeof(opmenu)); + for (opcode_index = 0; opcode_index < ctlr.menubytes; + opcode_index++) { + if (opmenu[opcode_index] == trans->opcode) + break; + } + + if (opcode_index == ctlr.menubytes) { + printf("ICH SPI: Opcode %x not found\n", + trans->opcode); + return -1; + } + + optypes = ich_readw(ctlr.optype); + optype = (optypes >> (opcode_index * 2)) & 0x3; + if (trans->type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS && + optype == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS && + trans->bytesout >= 3) { + /* We guessed wrong earlier. Fix it up. */ + trans->type = optype; + } + if (optype != trans->type) { + printf("ICH SPI: Transaction doesn't fit type %d\n", + optype); + return -1; + } + return opcode_index; + } +} + +static int spi_setup_offset(struct spi_trans *trans) +{ + /* Separate the SPI address and data. */ + switch (trans->type) { + case SPI_OPCODE_TYPE_READ_NO_ADDRESS: + case SPI_OPCODE_TYPE_WRITE_NO_ADDRESS: + return 0; + case SPI_OPCODE_TYPE_READ_WITH_ADDRESS: + case SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS: + trans->offset = ((uint32_t)trans->out[0] << 16) | + ((uint32_t)trans->out[1] << 8) | + ((uint32_t)trans->out[2] << 0); + spi_use_out(trans, 3); + return 1; + default: + printf("Unrecognized SPI transaction type %#x\n", trans->type); + return -1; + } +} + +/* + * Wait for up to 6s til status register bit(s) turn 1 (in case wait_til_set + * below is true) or 0. In case the wait was for the bit(s) to set - write + * those bits back, which would cause resetting them. + * + * Return the last read status value on success or -1 on failure. + */ +static int ich_status_poll(u16 bitmask, int wait_til_set) +{ + int timeout = 600000; /* This will result in 6s */ + u16 status = 0; + + while (timeout--) { + status = ich_readw(ctlr.status); + if (wait_til_set ^ ((status & bitmask) == 0)) { + if (wait_til_set) + ich_writew((status & bitmask), ctlr.status); + return status; + } + udelay(10); + } + + printf("ICH SPI: SCIP timeout, read %x, expected %x\n", + status, bitmask); + return -1; +} + +/* +int spi_xfer(struct spi_slave *slave, const void *dout, + unsigned int bitsout, void *din, unsigned int bitsin) +*/ +int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, + void *din, unsigned long flags) +{ + struct ich_spi_slave *ich = to_ich_spi(slave); + uint16_t control; + int16_t opcode_index; + int with_address; + int status; + int bytes = bitlen / 8; + struct spi_trans *trans = &ich->trans; + unsigned type = flags & (SPI_XFER_BEGIN | SPI_XFER_END); + int using_cmd = 0; + /* Align read transactions to 64-byte boundaries */ + char buff[ctlr.databytes]; + + /* Ee don't support writing partial bytes. */ + if (bitlen % 8) { + debug("ICH SPI: Accessing partial bytes not supported\n"); + return -1; + } + + /* An empty end transaction can be ignored */ + if (type == SPI_XFER_END && !dout && !din) + return 0; + + if (type & SPI_XFER_BEGIN) + memset(trans, '\0', sizeof(*trans)); + + /* Dp we need to come back later to finish it? */ + if (dout && type == SPI_XFER_BEGIN) { + if (bytes > ICH_MAX_CMD_LEN) { + debug("ICH SPI: Command length limit exceeded\n"); + return -1; + } + memcpy(trans->cmd, dout, bytes); + trans->cmd_len = bytes; + debug("ICH SPI: Saved %d bytes\n", bytes); + return 0; + } + + /* + * We process a 'middle' spi_xfer() call, which has no + * SPI_XFER_BEGIN/END, as an independent transaction as if it had + * an end. We therefore repeat the command. This is because ICH + * seems to have no support for this, or because interest (in digging + * out the details and creating a special case in the code) is low. + */ + if (trans->cmd_len) { + trans->out = trans->cmd; + trans->bytesout = trans->cmd_len; + using_cmd = 1; + debug("ICH SPI: Using %d bytes\n", trans->cmd_len); + } else { + trans->out = dout; + trans->bytesout = dout ? bytes : 0; + } + + trans->in = din; + trans->bytesin = din ? bytes : 0; + + /* There has to always at least be an opcode. */ + if (!trans->bytesout) { + debug("ICH SPI: No opcode for transfer\n"); + return -1; + } + + if (ich_status_poll(SPIS_SCIP, 0) == -1) + return -1; + + ich_writew(SPIS_CDS | SPIS_FCERR, ctlr.status); + + spi_setup_type(trans, using_cmd ? bytes : 0); + opcode_index = spi_setup_opcode(trans); + if (opcode_index < 0) + return -1; + with_address = spi_setup_offset(trans); + if (with_address < 0) + return -1; + + if (trans->opcode == SPI_OPCODE_WREN) { + /* + * Treat Write Enable as Atomic Pre-Op if possible + * in order to prevent the Management Engine from + * issuing a transaction between WREN and DATA. + */ + if (!ctlr.ichspi_lock) + ich_writew(trans->opcode, ctlr.preop); + return 0; + } + + if (ctlr.speed && ctlr.max_speed >= 33000000) { + int byte; + + byte = ich_readb(ctlr.speed); + if (ich->speed >= 33000000) + byte |= SSFC_SCF_33MHZ; + else + byte &= ~SSFC_SCF_33MHZ; + ich_writeb(byte, ctlr.speed); + } + + /* See if we have used up the command data */ + if (using_cmd && dout && bytes) { + trans->out = dout; + trans->bytesout = bytes; + debug("ICH SPI: Moving to data, %d bytes\n", bytes); + } + + /* Preset control fields */ + control = ich_readw(ctlr.control); + control &= ~SSFC_RESERVED; + control = SPIC_SCGO | ((opcode_index & 0x07) << 4); + + /* Issue atomic preop cycle if needed */ + if (ich_readw(ctlr.preop)) + control |= SPIC_ACS; + + if (!trans->bytesout && !trans->bytesin) { + /* SPI addresses are 24 bit only */ + if (with_address) + ich_writel(trans->offset & 0x00FFFFFF, ctlr.addr); + + /* + * This is a 'no data' command (like Write Enable), its + * bitesout size was 1, decremented to zero while executing + * spi_setup_opcode() above. Tell the chip to send the + * command. + */ + ich_writew(control, ctlr.control); + + /* wait for the result */ + status = ich_status_poll(SPIS_CDS | SPIS_FCERR, 1); + if (status == -1) + return -1; + + if (status & SPIS_FCERR) { + debug("ICH SPI: Command transaction error\n"); + return -1; + } + + return 0; + } + + /* + * Check if this is a write command atempting to transfer more bytes + * than the controller can handle. Iterations for writes are not + * supported here because each SPI write command needs to be preceded + * and followed by other SPI commands, and this sequence is controlled + * by the SPI chip driver. + */ + if (trans->bytesout > ctlr.databytes) { + debug("ICH SPI: Too much to write. This should be prevented by the driver's max_write_size?\n"); + return -1; + } + + /* + * Read or write up to databytes bytes at a time until everything has + * been sent. + */ + while (trans->bytesout || trans->bytesin) { + uint32_t data_length; + uint32_t aligned_offset; + uint32_t diff; + + aligned_offset = trans->offset & ~(ctlr.databytes - 1); + diff = trans->offset - aligned_offset; + + /* SPI addresses are 24 bit only */ + ich_writel(aligned_offset & 0x00FFFFFF, ctlr.addr); + + if (trans->bytesout) + data_length = min(trans->bytesout, ctlr.databytes); + else + data_length = min(trans->bytesin, ctlr.databytes); + + /* Program data into FDATA0 to N */ + if (trans->bytesout) { + write_reg(trans->out, ctlr.data, data_length); + spi_use_out(trans, data_length); + if (with_address) + trans->offset += data_length; + } + + /* Add proper control fields' values */ + control &= ~((ctlr.databytes - 1) << 8); + control |= SPIC_DS; + control |= (data_length - 1) << 8; + + /* write it */ + ich_writew(control, ctlr.control); + + /* Wait for Cycle Done Status or Flash Cycle Error. */ + status = ich_status_poll(SPIS_CDS | SPIS_FCERR, 1); + if (status == -1) + return -1; + + if (status & SPIS_FCERR) { + debug("ICH SPI: Data transaction error\n"); + return -1; + } + + if (trans->bytesin) { + if (diff) { + data_length -= diff; + read_reg(ctlr.data, buff, ctlr.databytes); + memcpy(trans->in, buff + diff, data_length); + } else { + read_reg(ctlr.data, trans->in, data_length); + } + spi_use_in(trans, data_length); + if (with_address) + trans->offset += data_length; + } + } + + /* Clear atomic preop now that xfer is done */ + ich_writew(0, ctlr.preop); + + return 0; +} + + +/* + * This uses the SPI controller from the Intel Cougar Point and Panther Point + * PCH to write-protect portions of the SPI flash until reboot. The changes + * don't actually take effect until the HSFS[FLOCKDN] bit is set, but that's + * done elsewhere. + */ +int spi_write_protect_region(uint32_t lower_limit, uint32_t length, int hint) +{ + uint32_t tmplong; + uint32_t upper_limit; + + if (!ctlr.pr) { + printf("%s: operation not supported on this chipset\n", + __func__); + return -1; + } + + if (length == 0 || + lower_limit > (0xFFFFFFFFUL - length) + 1 || + hint < 0 || hint > 4) { + printf("%s(0x%x, 0x%x, %d): invalid args\n", __func__, + lower_limit, length, hint); + return -1; + } + + upper_limit = lower_limit + length - 1; + + /* + * Determine bits to write, as follows: + * 31 Write-protection enable (includes erase operation) + * 30:29 reserved + * 28:16 Upper Limit (FLA address bits 24:12, with 11:0 == 0xfff) + * 15 Read-protection enable + * 14:13 reserved + * 12:0 Lower Limit (FLA address bits 24:12, with 11:0 == 0x000) + */ + tmplong = 0x80000000 | + ((upper_limit & 0x01fff000) << 4) | + ((lower_limit & 0x01fff000) >> 12); + + printf("%s: writing 0x%08x to %p\n", __func__, tmplong, + &ctlr.pr[hint]); + ctlr.pr[hint] = tmplong; + + return 0; +} diff --git a/drivers/spi/ich.h b/drivers/spi/ich.h new file mode 100644 index 0000000..bd7bc12 --- /dev/null +++ b/drivers/spi/ich.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * This file is derived from the flashrom project. + */ + +struct ich7_spi_regs { + uint16_t spis; + uint16_t spic; + uint32_t spia; + uint64_t spid[8]; + uint64_t _pad; + uint32_t bbar; + uint16_t preop; + uint16_t optype; + uint8_t opmenu[8]; +} __packed; + +struct ich9_spi_regs { + uint32_t bfpr; /* 0x00 */ + uint16_t hsfs; + uint16_t hsfc; + uint32_t faddr; + uint32_t _reserved0; + uint32_t fdata[16]; /* 0x10 */ + uint32_t frap; /* 0x50 */ + uint32_t freg[5]; + uint32_t _reserved1[3]; + uint32_t pr[5]; /* 0x74 */ + uint32_t _reserved2[2]; + uint8_t ssfs; /* 0x90 */ + uint8_t ssfc[3]; + uint16_t preop; /* 0x94 */ + uint16_t optype; + uint8_t opmenu[8]; /* 0x98 */ + uint32_t bbar; + uint8_t _reserved3[12]; + uint32_t fdoc; + uint32_t fdod; + uint8_t _reserved4[8]; + uint32_t afc; + uint32_t lvscc; + uint32_t uvscc; + uint8_t _reserved5[4]; + uint32_t fpb; + uint8_t _reserved6[28]; + uint32_t srdl; + uint32_t srdc; + uint32_t srd; +} __packed; + +enum { + SPIS_SCIP = 0x0001, + SPIS_GRANT = 0x0002, + SPIS_CDS = 0x0004, + SPIS_FCERR = 0x0008, + SSFS_AEL = 0x0010, + SPIS_LOCK = 0x8000, + SPIS_RESERVED_MASK = 0x7ff0, + SSFS_RESERVED_MASK = 0x7fe2 +}; + +enum { + SPIC_SCGO = 0x000002, + SPIC_ACS = 0x000004, + SPIC_SPOP = 0x000008, + SPIC_DBC = 0x003f00, + SPIC_DS = 0x004000, + SPIC_SME = 0x008000, + SSFC_SCF_MASK = 0x070000, + SSFC_RESERVED = 0xf80000, + + /* Mask for speed byte, biuts 23:16 of SSFC */ + SSFC_SCF_33MHZ = 0x01, +}; + +enum { + HSFS_FDONE = 0x0001, + HSFS_FCERR = 0x0002, + HSFS_AEL = 0x0004, + HSFS_BERASE_MASK = 0x0018, + HSFS_BERASE_SHIFT = 3, + HSFS_SCIP = 0x0020, + HSFS_FDOPSS = 0x2000, + HSFS_FDV = 0x4000, + HSFS_FLOCKDN = 0x8000 +}; + +enum { + HSFC_FGO = 0x0001, + HSFC_FCYCLE_MASK = 0x0006, + HSFC_FCYCLE_SHIFT = 1, + HSFC_FDBC_MASK = 0x3f00, + HSFC_FDBC_SHIFT = 8, + HSFC_FSMIE = 0x8000 +}; + +enum { + SPI_OPCODE_TYPE_READ_NO_ADDRESS = 0, + SPI_OPCODE_TYPE_WRITE_NO_ADDRESS = 1, + SPI_OPCODE_TYPE_READ_WITH_ADDRESS = 2, + SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS = 3 +}; + +enum { + ICH_MAX_CMD_LEN = 5, +}; + +struct spi_trans { + uint8_t cmd[ICH_MAX_CMD_LEN]; + int cmd_len; + const uint8_t *out; + uint32_t bytesout; + uint8_t *in; + uint32_t bytesin; + uint8_t type; + uint8_t opcode; + uint32_t offset; +}; + +struct ich_spi_slave { + struct spi_slave slave; + struct spi_trans trans; /* current transaction in progress */ + int speed; /* SPI speed in Hz */ +}; diff --git a/drivers/spi/kirkwood_spi.c b/drivers/spi/kirkwood_spi.c index de81064..caa91e3 100644 --- a/drivers/spi/kirkwood_spi.c +++ b/drivers/spi/kirkwood_spi.c @@ -49,13 +49,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, if (!spi_cs_is_valid(bus, cs)) return NULL; - slave = malloc(sizeof(struct spi_slave)); + slave = spi_alloc_slave_base(bus, cs); if (!slave) return NULL; - slave->bus = bus; - slave->cs = cs; - writel(~KWSPI_CSN_ACT | KWSPI_SMEMRDY, &spireg->ctrl); /* calculate spi clock prescaller using max_hz */ diff --git a/drivers/spi/mpc52xx_spi.c b/drivers/spi/mpc52xx_spi.c index 3e96b3f..4b50bca 100644 --- a/drivers/spi/mpc52xx_spi.c +++ b/drivers/spi/mpc52xx_spi.c @@ -48,13 +48,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, { struct spi_slave *slave; - slave = malloc(sizeof(struct spi_slave)); + slave = spi_alloc_slave_base(bus, cs); if (!slave) return NULL; - slave->bus = bus; - slave->cs = cs; - return slave; } diff --git a/drivers/spi/mpc8xxx_spi.c b/drivers/spi/mpc8xxx_spi.c index 4e46041..6b0e3b4 100644 --- a/drivers/spi/mpc8xxx_spi.c +++ b/drivers/spi/mpc8xxx_spi.c @@ -45,13 +45,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, if (!spi_cs_is_valid(bus, cs)) return NULL; - slave = malloc(sizeof(struct spi_slave)); + slave = spi_alloc_slave_base(bus, cs); if (!slave) return NULL; - slave->bus = bus; - slave->cs = cs; - /* * TODO: Some of the code in spi_init() should probably move * here, or into spi_claim_bus() below. diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c index 20419e6..5bed858 100644 --- a/drivers/spi/mxc_spi.c +++ b/drivers/spi/mxc_spi.c @@ -409,7 +409,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, if (bus >= ARRAY_SIZE(spi_bases)) return NULL; - mxcs = calloc(sizeof(struct mxc_spi_slave), 1); + mxcs = spi_alloc_slave(struct mxc_spi_slave, bus, cs); if (!mxcs) { puts("mxc_spi: SPI Slave not allocated !\n"); return NULL; @@ -425,8 +425,6 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, cs = ret; - mxcs->slave.bus = bus; - mxcs->slave.cs = cs; mxcs->base = spi_bases[bus]; ret = spi_cfg_mxc(mxcs, cs, max_hz, mode); diff --git a/drivers/spi/mxs_spi.c b/drivers/spi/mxs_spi.c index ffa3c1d..aa999f9 100644 --- a/drivers/spi/mxs_spi.c +++ b/drivers/spi/mxs_spi.c @@ -77,15 +77,13 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, return NULL; } - mxs_slave = calloc(sizeof(struct mxs_spi_slave), 1); + mxs_slave = spi_alloc_slave(struct mxs_spi_slave, bus, cs); if (!mxs_slave) return NULL; if (mxs_dma_init_channel(MXS_DMA_CHANNEL_AHB_APBH_SSP0 + bus)) goto err_init; - mxs_slave->slave.bus = bus; - mxs_slave->slave.cs = cs; mxs_slave->max_khz = max_hz / 1000; mxs_slave->mode = mode; mxs_slave->regs = mxs_ssp_regs_by_bus(bus); diff --git a/drivers/spi/oc_tiny_spi.c b/drivers/spi/oc_tiny_spi.c index fc01fb8..6f7b1ed 100644 --- a/drivers/spi/oc_tiny_spi.c +++ b/drivers/spi/oc_tiny_spi.c @@ -90,13 +90,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, if (!spi_cs_is_valid(bus, cs) || gpio_request(cs, "tiny_spi")) return NULL; - tiny_spi = malloc(sizeof(*tiny_spi)); + tiny_spi = spi_alloc_slave(struct tiny_spi_slave, bus, cs); if (!tiny_spi) return NULL; - memset(tiny_spi, 0, sizeof(*tiny_spi)); - tiny_spi->slave.bus = bus; - tiny_spi->slave.cs = cs; tiny_spi->host = &tiny_spi_host_list[bus]; tiny_spi->mode = mode & (SPI_CPOL | SPI_CPHA); tiny_spi->flg = mode & SPI_CS_HIGH ? 1 : 0; diff --git a/drivers/spi/omap3_spi.c b/drivers/spi/omap3_spi.c index 344d5b8..80a4e47 100644 --- a/drivers/spi/omap3_spi.c +++ b/drivers/spi/omap3_spi.c @@ -80,12 +80,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, unsigned int max_hz, unsigned int mode) { struct omap3_spi_slave *ds; - - ds = malloc(sizeof(struct omap3_spi_slave)); - if (!ds) { - printf("SPI error: malloc of SPI structure failed\n"); - return NULL; - } + struct mcspi *regs; /* * OMAP3 McSPI (MultiChannel SPI) has 4 busses (modules) @@ -98,21 +93,21 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, switch (bus) { case 0: - ds->regs = (struct mcspi *)OMAP3_MCSPI1_BASE; + regs = (struct mcspi *)OMAP3_MCSPI1_BASE; break; #ifdef OMAP3_MCSPI2_BASE case 1: - ds->regs = (struct mcspi *)OMAP3_MCSPI2_BASE; + regs = (struct mcspi *)OMAP3_MCSPI2_BASE; break; #endif #ifdef OMAP3_MCSPI3_BASE case 2: - ds->regs = (struct mcspi *)OMAP3_MCSPI3_BASE; + regs = (struct mcspi *)OMAP3_MCSPI3_BASE; break; #endif #ifdef OMAP3_MCSPI4_BASE case 3: - ds->regs = (struct mcspi *)OMAP3_MCSPI4_BASE; + regs = (struct mcspi *)OMAP3_MCSPI4_BASE; break; #endif default: @@ -120,7 +115,6 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, Supported busses 0 - 3\n", bus); return NULL; } - ds->slave.bus = bus; if (((bus == 0) && (cs > 3)) || ((bus == 1) && (cs > 1)) || @@ -130,19 +124,26 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, on bus %i\n", cs, bus); return NULL; } - ds->slave.cs = cs; if (max_hz > OMAP3_MCSPI_MAX_FREQ) { printf("SPI error: unsupported frequency %i Hz. \ Max frequency is 48 Mhz\n", max_hz); return NULL; } - ds->freq = max_hz; if (mode > SPI_MODE_3) { printf("SPI error: unsupported SPI mode %i\n", mode); return NULL; } + + ds = spi_alloc_slave(struct omap3_spi_slave, bus, cs); + if (!ds) { + printf("SPI error: malloc of SPI structure failed\n"); + return NULL; + } + + ds->regs = regs; + ds->freq = max_hz; ds->mode = mode; return &ds->slave; diff --git a/drivers/spi/sh_spi.c b/drivers/spi/sh_spi.c index e944b23..744afe3 100644 --- a/drivers/spi/sh_spi.c +++ b/drivers/spi/sh_spi.c @@ -103,12 +103,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, if (!spi_cs_is_valid(bus, cs)) return NULL; - ss = malloc(sizeof(struct spi_slave)); + ss = spi_alloc_slave(struct sh_spi, bus, cs); if (!ss) return NULL; - ss->slave.bus = bus; - ss->slave.cs = cs; ss->regs = (struct sh_spi_regs *)CONFIG_SH_SPI_BASE; /* SPI sycle stop */ diff --git a/drivers/spi/soft_spi.c b/drivers/spi/soft_spi.c index 13df8cb..a1b84b6 100644 --- a/drivers/spi/soft_spi.c +++ b/drivers/spi/soft_spi.c @@ -73,12 +73,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, if (!spi_cs_is_valid(bus, cs)) return NULL; - ss = malloc(sizeof(struct soft_spi_slave)); + ss = spi_alloc_slave(struct soft_spi_slave, bus, cs); if (!ss) return NULL; - ss->slave.bus = bus; - ss->slave.cs = cs; ss->mode = mode; /* TODO: Use max_hz to limit the SCK rate */ diff --git a/drivers/usb/host/s3c64xx-hcd.c b/drivers/spi/spi.c index cd295da..cb36c5e 100644 --- a/drivers/usb/host/s3c64xx-hcd.c +++ b/drivers/spi/spi.c @@ -1,11 +1,5 @@ /* - * URB OHCI HCD (Host Controller Driver) initialization for USB on the S3C64XX. - * - * Copyright (C) 2008, - * Guennadi Liakhovetski, DENX Software Engineering <lg@denx.de> - * - * See file CREDITS for list of people who contributed to this - * project. + * Copyright (c) 2011 The Chromium OS Authors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -13,7 +7,7 @@ * 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 + * 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. * @@ -21,25 +15,25 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA - * */ #include <common.h> -#include <asm/arch/s3c6400.h> +#include <malloc.h> +#include <spi.h> -int usb_cpu_init(void) +void *spi_do_alloc_slave(int offset, int size, unsigned int bus, + unsigned int cs) { - OTHERS_REG |= 0x10000; - return 0; -} + struct spi_slave *slave; + void *ptr; -int usb_cpu_stop(void) -{ - OTHERS_REG &= ~0x10000; - return 0; -} + ptr = malloc(size); + if (ptr) { + memset(ptr, '\0', size); + slave = (struct spi_slave *)(ptr + offset); + slave->bus = bus; + slave->cs = cs; + } -void usb_cpu_init_fail(void) -{ - OTHERS_REG &= ~0x10000; + return ptr; } diff --git a/drivers/spi/tegra114_spi.c b/drivers/spi/tegra114_spi.c new file mode 100644 index 0000000..b11a0a1 --- /dev/null +++ b/drivers/spi/tegra114_spi.c @@ -0,0 +1,405 @@ +/* + * NVIDIA Tegra SPI controller (T114 and later) + * + * Copyright (c) 2010-2013 NVIDIA Corporation + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <malloc.h> +#include <asm/io.h> +#include <asm/gpio.h> +#include <asm/arch/clock.h> +#include <asm/arch-tegra/clk_rst.h> +#include <asm/arch-tegra114/tegra114_spi.h> +#include <spi.h> +#include <fdtdec.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* COMMAND1 */ +#define SPI_CMD1_GO (1 << 31) +#define SPI_CMD1_M_S (1 << 30) +#define SPI_CMD1_MODE_MASK 0x3 +#define SPI_CMD1_MODE_SHIFT 28 +#define SPI_CMD1_CS_SEL_MASK 0x3 +#define SPI_CMD1_CS_SEL_SHIFT 26 +#define SPI_CMD1_CS_POL_INACTIVE3 (1 << 25) +#define SPI_CMD1_CS_POL_INACTIVE2 (1 << 24) +#define SPI_CMD1_CS_POL_INACTIVE1 (1 << 23) +#define SPI_CMD1_CS_POL_INACTIVE0 (1 << 22) +#define SPI_CMD1_CS_SW_HW (1 << 21) +#define SPI_CMD1_CS_SW_VAL (1 << 20) +#define SPI_CMD1_IDLE_SDA_MASK 0x3 +#define SPI_CMD1_IDLE_SDA_SHIFT 18 +#define SPI_CMD1_BIDIR (1 << 17) +#define SPI_CMD1_LSBI_FE (1 << 16) +#define SPI_CMD1_LSBY_FE (1 << 15) +#define SPI_CMD1_BOTH_EN_BIT (1 << 14) +#define SPI_CMD1_BOTH_EN_BYTE (1 << 13) +#define SPI_CMD1_RX_EN (1 << 12) +#define SPI_CMD1_TX_EN (1 << 11) +#define SPI_CMD1_PACKED (1 << 5) +#define SPI_CMD1_BIT_LEN_MASK 0x1F +#define SPI_CMD1_BIT_LEN_SHIFT 0 + +/* COMMAND2 */ +#define SPI_CMD2_TX_CLK_TAP_DELAY (1 << 6) +#define SPI_CMD2_TX_CLK_TAP_DELAY_MASK (0x3F << 6) +#define SPI_CMD2_RX_CLK_TAP_DELAY (1 << 0) +#define SPI_CMD2_RX_CLK_TAP_DELAY_MASK (0x3F << 0) + +/* TRANSFER STATUS */ +#define SPI_XFER_STS_RDY (1 << 30) + +/* FIFO STATUS */ +#define SPI_FIFO_STS_CS_INACTIVE (1 << 31) +#define SPI_FIFO_STS_FRAME_END (1 << 30) +#define SPI_FIFO_STS_RX_FIFO_FLUSH (1 << 15) +#define SPI_FIFO_STS_TX_FIFO_FLUSH (1 << 14) +#define SPI_FIFO_STS_ERR (1 << 8) +#define SPI_FIFO_STS_TX_FIFO_OVF (1 << 7) +#define SPI_FIFO_STS_TX_FIFO_UNR (1 << 6) +#define SPI_FIFO_STS_RX_FIFO_OVF (1 << 5) +#define SPI_FIFO_STS_RX_FIFO_UNR (1 << 4) +#define SPI_FIFO_STS_TX_FIFO_FULL (1 << 3) +#define SPI_FIFO_STS_TX_FIFO_EMPTY (1 << 2) +#define SPI_FIFO_STS_RX_FIFO_FULL (1 << 1) +#define SPI_FIFO_STS_RX_FIFO_EMPTY (1 << 0) + +#define SPI_TIMEOUT 1000 +#define TEGRA_SPI_MAX_FREQ 52000000 + +struct spi_regs { + u32 command1; /* 000:SPI_COMMAND1 register */ + u32 command2; /* 004:SPI_COMMAND2 register */ + u32 timing1; /* 008:SPI_CS_TIM1 register */ + u32 timing2; /* 00c:SPI_CS_TIM2 register */ + u32 xfer_status;/* 010:SPI_TRANS_STATUS register */ + u32 fifo_status;/* 014:SPI_FIFO_STATUS register */ + u32 tx_data; /* 018:SPI_TX_DATA register */ + u32 rx_data; /* 01c:SPI_RX_DATA register */ + u32 dma_ctl; /* 020:SPI_DMA_CTL register */ + u32 dma_blk; /* 024:SPI_DMA_BLK register */ + u32 rsvd[56]; /* 028-107 reserved */ + u32 tx_fifo; /* 108:SPI_FIFO1 register */ + u32 rsvd2[31]; /* 10c-187 reserved */ + u32 rx_fifo; /* 188:SPI_FIFO2 register */ + u32 spare_ctl; /* 18c:SPI_SPARE_CTRL register */ +}; + +struct tegra_spi_ctrl { + struct spi_regs *regs; + unsigned int freq; + unsigned int mode; + int periph_id; + int valid; +}; + +struct tegra_spi_slave { + struct spi_slave slave; + struct tegra_spi_ctrl *ctrl; +}; + +static struct tegra_spi_ctrl spi_ctrls[CONFIG_TEGRA114_SPI_CTRLS]; + +static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave) +{ + return container_of(slave, struct tegra_spi_slave, slave); +} + +int tegra114_spi_cs_is_valid(unsigned int bus, unsigned int cs) +{ + if (bus >= CONFIG_TEGRA114_SPI_CTRLS || cs > 3 || !spi_ctrls[bus].valid) + return 0; + else + return 1; +} + +struct spi_slave *tegra114_spi_setup_slave(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode) +{ + struct tegra_spi_slave *spi; + + debug("%s: bus: %u, cs: %u, max_hz: %u, mode: %u\n", __func__, + bus, cs, max_hz, mode); + + if (!spi_cs_is_valid(bus, cs)) { + printf("SPI error: unsupported bus %d / chip select %d\n", + bus, cs); + return NULL; + } + + if (max_hz > TEGRA_SPI_MAX_FREQ) { + printf("SPI error: unsupported frequency %d Hz. Max frequency" + " is %d Hz\n", max_hz, TEGRA_SPI_MAX_FREQ); + return NULL; + } + + spi = malloc(sizeof(struct tegra_spi_slave)); + if (!spi) { + printf("SPI error: malloc of SPI structure failed\n"); + return NULL; + } + spi->slave.bus = bus; + spi->slave.cs = cs; + spi->ctrl = &spi_ctrls[bus]; + if (!spi->ctrl) { + printf("SPI error: could not find controller for bus %d\n", + bus); + return NULL; + } + + if (max_hz < spi->ctrl->freq) { + debug("%s: limiting frequency from %u to %u\n", __func__, + spi->ctrl->freq, max_hz); + spi->ctrl->freq = max_hz; + } + spi->ctrl->mode = mode; + + return &spi->slave; +} + +void tegra114_spi_free_slave(struct spi_slave *slave) +{ + struct tegra_spi_slave *spi = to_tegra_spi(slave); + + free(spi); +} + +int tegra114_spi_init(int *node_list, int count) +{ + struct tegra_spi_ctrl *ctrl; + int i; + int node = 0; + int found = 0; + + for (i = 0; i < count; i++) { + ctrl = &spi_ctrls[i]; + node = node_list[i]; + + ctrl->regs = (struct spi_regs *)fdtdec_get_addr(gd->fdt_blob, + node, "reg"); + if ((fdt_addr_t)ctrl->regs == FDT_ADDR_T_NONE) { + debug("%s: no spi register found\n", __func__); + continue; + } + ctrl->freq = fdtdec_get_int(gd->fdt_blob, node, + "spi-max-frequency", 0); + if (!ctrl->freq) { + debug("%s: no spi max frequency found\n", __func__); + continue; + } + + ctrl->periph_id = clock_decode_periph_id(gd->fdt_blob, node); + if (ctrl->periph_id == PERIPH_ID_NONE) { + debug("%s: could not decode periph id\n", __func__); + continue; + } + ctrl->valid = 1; + found = 1; + + debug("%s: found controller at %p, freq = %u, periph_id = %d\n", + __func__, ctrl->regs, ctrl->freq, ctrl->periph_id); + } + + return !found; +} + +int tegra114_spi_claim_bus(struct spi_slave *slave) +{ + struct tegra_spi_slave *spi = to_tegra_spi(slave); + struct spi_regs *regs = spi->ctrl->regs; + + /* Change SPI clock to correct frequency, PLLP_OUT0 source */ + clock_start_periph_pll(spi->ctrl->periph_id, CLOCK_ID_PERIPH, + spi->ctrl->freq); + + /* Clear stale status here */ + setbits_le32(®s->fifo_status, + SPI_FIFO_STS_ERR | + SPI_FIFO_STS_TX_FIFO_OVF | + SPI_FIFO_STS_TX_FIFO_UNR | + SPI_FIFO_STS_RX_FIFO_OVF | + SPI_FIFO_STS_RX_FIFO_UNR | + SPI_FIFO_STS_TX_FIFO_FULL | + SPI_FIFO_STS_TX_FIFO_EMPTY | + SPI_FIFO_STS_RX_FIFO_FULL | + SPI_FIFO_STS_RX_FIFO_EMPTY); + debug("%s: FIFO STATUS = %08x\n", __func__, readl(®s->fifo_status)); + + /* Set master mode and sw controlled CS */ + setbits_le32(®s->command1, SPI_CMD1_M_S | SPI_CMD1_CS_SW_HW | + (spi->ctrl->mode << SPI_CMD1_MODE_SHIFT)); + debug("%s: COMMAND1 = %08x\n", __func__, readl(®s->command1)); + + return 0; +} + +void tegra114_spi_cs_activate(struct spi_slave *slave) +{ + struct tegra_spi_slave *spi = to_tegra_spi(slave); + struct spi_regs *regs = spi->ctrl->regs; + + clrbits_le32(®s->command1, SPI_CMD1_CS_SW_VAL); +} + +void tegra114_spi_cs_deactivate(struct spi_slave *slave) +{ + struct tegra_spi_slave *spi = to_tegra_spi(slave); + struct spi_regs *regs = spi->ctrl->regs; + + setbits_le32(®s->command1, SPI_CMD1_CS_SW_VAL); +} + +int tegra114_spi_xfer(struct spi_slave *slave, unsigned int bitlen, + const void *data_out, void *data_in, unsigned long flags) +{ + struct tegra_spi_slave *spi = to_tegra_spi(slave); + struct spi_regs *regs = spi->ctrl->regs; + u32 reg, tmpdout, tmpdin = 0; + const u8 *dout = data_out; + u8 *din = data_in; + int num_bytes; + int ret; + + debug("%s: slave %u:%u dout %p din %p bitlen %u\n", + __func__, slave->bus, slave->cs, dout, din, bitlen); + if (bitlen % 8) + return -1; + num_bytes = bitlen / 8; + + ret = 0; + + /* clear all error status bits */ + reg = readl(®s->fifo_status); + writel(reg, ®s->fifo_status); + + /* clear ready bit */ + setbits_le32(®s->xfer_status, SPI_XFER_STS_RDY); + + clrsetbits_le32(®s->command1, SPI_CMD1_CS_SW_VAL, + SPI_CMD1_RX_EN | SPI_CMD1_TX_EN | SPI_CMD1_LSBY_FE | + (slave->cs << SPI_CMD1_CS_SEL_SHIFT)); + + /* set xfer size to 1 block (32 bits) */ + writel(0, ®s->dma_blk); + + if (flags & SPI_XFER_BEGIN) + spi_cs_activate(slave); + + /* handle data in 32-bit chunks */ + while (num_bytes > 0) { + int bytes; + int is_read = 0; + int tm, i; + + tmpdout = 0; + bytes = (num_bytes > 4) ? 4 : num_bytes; + + if (dout != NULL) { + for (i = 0; i < bytes; ++i) + tmpdout = (tmpdout << 8) | dout[i]; + dout += bytes; + } + + num_bytes -= bytes; + + clrsetbits_le32(®s->command1, + SPI_CMD1_BIT_LEN_MASK << SPI_CMD1_BIT_LEN_SHIFT, + (bytes * 8 - 1) << SPI_CMD1_BIT_LEN_SHIFT); + writel(tmpdout, ®s->tx_fifo); + setbits_le32(®s->command1, SPI_CMD1_GO); + + /* + * Wait for SPI transmit FIFO to empty, or to time out. + * The RX FIFO status will be read and cleared last + */ + for (tm = 0, is_read = 0; tm < SPI_TIMEOUT; ++tm) { + u32 fifo_status, xfer_status; + + fifo_status = readl(®s->fifo_status); + + /* We can exit when we've had both RX and TX activity */ + if (is_read && + (fifo_status & SPI_FIFO_STS_TX_FIFO_EMPTY)) + break; + + xfer_status = readl(®s->xfer_status); + if (!(xfer_status & SPI_XFER_STS_RDY)) + continue; + + if (fifo_status & SPI_FIFO_STS_ERR) { + debug("%s: got a fifo error: ", __func__); + if (fifo_status & SPI_FIFO_STS_TX_FIFO_OVF) + debug("tx FIFO overflow "); + if (fifo_status & SPI_FIFO_STS_TX_FIFO_UNR) + debug("tx FIFO underrun "); + if (fifo_status & SPI_FIFO_STS_RX_FIFO_OVF) + debug("rx FIFO overflow "); + if (fifo_status & SPI_FIFO_STS_RX_FIFO_UNR) + debug("rx FIFO underrun "); + if (fifo_status & SPI_FIFO_STS_TX_FIFO_FULL) + debug("tx FIFO full "); + if (fifo_status & SPI_FIFO_STS_TX_FIFO_EMPTY) + debug("tx FIFO empty "); + if (fifo_status & SPI_FIFO_STS_RX_FIFO_FULL) + debug("rx FIFO full "); + if (fifo_status & SPI_FIFO_STS_RX_FIFO_EMPTY) + debug("rx FIFO empty "); + debug("\n"); + break; + } + + if (!(fifo_status & SPI_FIFO_STS_RX_FIFO_EMPTY)) { + tmpdin = readl(®s->rx_fifo); + is_read = 1; + + /* swap bytes read in */ + if (din != NULL) { + for (i = bytes - 1; i >= 0; --i) { + din[i] = tmpdin & 0xff; + tmpdin >>= 8; + } + din += bytes; + } + } + } + + if (tm >= SPI_TIMEOUT) + ret = tm; + + /* clear ACK RDY, etc. bits */ + writel(readl(®s->fifo_status), ®s->fifo_status); + } + + if (flags & SPI_XFER_END) + spi_cs_deactivate(slave); + + debug("%s: transfer ended. Value=%08x, fifo_status = %08x\n", + __func__, tmpdin, readl(®s->fifo_status)); + + if (ret) { + printf("%s: timeout during SPI transfer, tm %d\n", + __func__, ret); + return -1; + } + + return 0; +} diff --git a/drivers/spi/tegra_spi.c b/drivers/spi/tegra20_sflash.c index ce19095..9322ce7 100644 --- a/drivers/spi/tegra_spi.c +++ b/drivers/spi/tegra20_sflash.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2012 NVIDIA Corporation + * Copyright (c) 2010-2013 NVIDIA Corporation * With help from the mpc8xxx SPI driver * With more help from omap3_spi SPI driver * @@ -28,34 +28,80 @@ #include <asm/gpio.h> #include <asm/arch/clock.h> #include <asm/arch/pinmux.h> -#include <asm/arch/uart-spi-switch.h> #include <asm/arch-tegra/clk_rst.h> -#include <asm/arch-tegra/tegra_spi.h> +#include <asm/arch-tegra20/tegra20_sflash.h> #include <spi.h> #include <fdtdec.h> DECLARE_GLOBAL_DATA_PTR; -#if defined(CONFIG_SPI_CORRUPTS_UART) - #define corrupt_delay() udelay(CONFIG_SPI_CORRUPTS_UART_DLY); -#else - #define corrupt_delay() -#endif +#define SPI_CMD_GO (1 << 30) +#define SPI_CMD_ACTIVE_SCLK_SHIFT 26 +#define SPI_CMD_ACTIVE_SCLK_MASK (3 << SPI_CMD_ACTIVE_SCLK_SHIFT) +#define SPI_CMD_CK_SDA (1 << 21) +#define SPI_CMD_ACTIVE_SDA_SHIFT 18 +#define SPI_CMD_ACTIVE_SDA_MASK (3 << SPI_CMD_ACTIVE_SDA_SHIFT) +#define SPI_CMD_CS_POL (1 << 16) +#define SPI_CMD_TXEN (1 << 15) +#define SPI_CMD_RXEN (1 << 14) +#define SPI_CMD_CS_VAL (1 << 13) +#define SPI_CMD_CS_SOFT (1 << 12) +#define SPI_CMD_CS_DELAY (1 << 9) +#define SPI_CMD_CS3_EN (1 << 8) +#define SPI_CMD_CS2_EN (1 << 7) +#define SPI_CMD_CS1_EN (1 << 6) +#define SPI_CMD_CS0_EN (1 << 5) +#define SPI_CMD_BIT_LENGTH (1 << 4) +#define SPI_CMD_BIT_LENGTH_MASK 0x0000001F + +#define SPI_STAT_BSY (1 << 31) +#define SPI_STAT_RDY (1 << 30) +#define SPI_STAT_RXF_FLUSH (1 << 29) +#define SPI_STAT_TXF_FLUSH (1 << 28) +#define SPI_STAT_RXF_UNR (1 << 27) +#define SPI_STAT_TXF_OVF (1 << 26) +#define SPI_STAT_RXF_EMPTY (1 << 25) +#define SPI_STAT_RXF_FULL (1 << 24) +#define SPI_STAT_TXF_EMPTY (1 << 23) +#define SPI_STAT_TXF_FULL (1 << 22) +#define SPI_STAT_SEL_TXRX_N (1 << 16) +#define SPI_STAT_CUR_BLKCNT (1 << 15) + +#define SPI_TIMEOUT 1000 +#define TEGRA_SPI_MAX_FREQ 52000000 + +struct spi_regs { + u32 command; /* SPI_COMMAND_0 register */ + u32 status; /* SPI_STATUS_0 register */ + u32 rx_cmp; /* SPI_RX_CMP_0 register */ + u32 dma_ctl; /* SPI_DMA_CTL_0 register */ + u32 tx_fifo; /* SPI_TX_FIFO_0 register */ + u32 rsvd[3]; /* offsets 0x14 to 0x1F reserved */ + u32 rx_fifo; /* SPI_RX_FIFO_0 register */ +}; -struct tegra_spi_slave { - struct spi_slave slave; - struct spi_tegra *regs; +struct tegra_spi_ctrl { + struct spi_regs *regs; unsigned int freq; unsigned int mode; int periph_id; + int valid; }; +struct tegra_spi_slave { + struct spi_slave slave; + struct tegra_spi_ctrl *ctrl; +}; + +/* tegra20 only supports one SFLASH controller */ +static struct tegra_spi_ctrl spi_ctrls[1]; + static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave) { return container_of(slave, struct tegra_spi_slave, slave); } -int spi_cs_is_valid(unsigned int bus, unsigned int cs) +int tegra20_spi_cs_is_valid(unsigned int bus, unsigned int cs) { /* Tegra20 SPI-Flash - only 1 device ('bus/cs') */ if (bus != 0 || cs != 0) @@ -64,8 +110,8 @@ int spi_cs_is_valid(unsigned int bus, unsigned int cs) return 1; } -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) +struct spi_slave *tegra20_spi_setup_slave(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode) { struct tegra_spi_slave *spi; @@ -81,93 +127,100 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, return NULL; } - spi = malloc(sizeof(struct tegra_spi_slave)); + spi = spi_alloc_slave(struct tegra_spi_slave, bus, cs); if (!spi) { printf("SPI error: malloc of SPI structure failed\n"); return NULL; } spi->slave.bus = bus; spi->slave.cs = cs; -#ifdef CONFIG_OF_CONTROL - int node = fdtdec_next_compatible(gd->fdt_blob, 0, - COMPAT_NVIDIA_TEGRA20_SFLASH); - if (node < 0) { - debug("%s: cannot locate sflash node\n", __func__); + spi->ctrl = &spi_ctrls[bus]; + if (!spi->ctrl) { + printf("SPI error: could not find controller for bus %d\n", + bus); return NULL; } - if (!fdtdec_get_is_enabled(gd->fdt_blob, node)) { - debug("%s: sflash is disabled\n", __func__); - return NULL; - } - spi->regs = (struct spi_tegra *)fdtdec_get_addr(gd->fdt_blob, - node, "reg"); - if ((fdt_addr_t)spi->regs == FDT_ADDR_T_NONE) { - debug("%s: no sflash register found\n", __func__); - return NULL; - } - spi->freq = fdtdec_get_int(gd->fdt_blob, node, "spi-max-frequency", 0); - if (!spi->freq) { - debug("%s: no sflash max frequency found\n", __func__); - return NULL; - } - spi->periph_id = clock_decode_periph_id(gd->fdt_blob, node); - if (spi->periph_id == PERIPH_ID_NONE) { - debug("%s: could not decode periph id\n", __func__); - return NULL; - } -#else - spi->regs = (struct spi_tegra *)NV_PA_SPI_BASE; - spi->freq = TEGRA_SPI_MAX_FREQ; - spi->periph_id = PERIPH_ID_SPI1; -#endif - if (max_hz < spi->freq) { + + if (max_hz < spi->ctrl->freq) { debug("%s: limiting frequency from %u to %u\n", __func__, - spi->freq, max_hz); - spi->freq = max_hz; + spi->ctrl->freq, max_hz); + spi->ctrl->freq = max_hz; } - debug("%s: controller initialized at %p, freq = %u, periph_id = %d\n", - __func__, spi->regs, spi->freq, spi->periph_id); - spi->mode = mode; + spi->ctrl->mode = mode; return &spi->slave; } -void spi_free_slave(struct spi_slave *slave) +void tegra20_spi_free_slave(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); free(spi); } -void spi_init(void) +int tegra20_spi_init(int *node_list, int count) { - /* do nothing */ + struct tegra_spi_ctrl *ctrl; + int i; + int node = 0; + int found = 0; + + for (i = 0; i < count; i++) { + ctrl = &spi_ctrls[i]; + node = node_list[i]; + + ctrl->regs = (struct spi_regs *)fdtdec_get_addr(gd->fdt_blob, + node, "reg"); + if ((fdt_addr_t)ctrl->regs == FDT_ADDR_T_NONE) { + debug("%s: no slink register found\n", __func__); + continue; + } + ctrl->freq = fdtdec_get_int(gd->fdt_blob, node, + "spi-max-frequency", 0); + if (!ctrl->freq) { + debug("%s: no slink max frequency found\n", __func__); + continue; + } + + ctrl->periph_id = clock_decode_periph_id(gd->fdt_blob, node); + if (ctrl->periph_id == PERIPH_ID_NONE) { + debug("%s: could not decode periph id\n", __func__); + continue; + } + ctrl->valid = 1; + found = 1; + + debug("%s: found controller at %p, freq = %u, periph_id = %d\n", + __func__, ctrl->regs, ctrl->freq, ctrl->periph_id); + } + return !found; } -int spi_claim_bus(struct spi_slave *slave) +int tegra20_spi_claim_bus(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); - struct spi_tegra *regs = spi->regs; + struct spi_regs *regs = spi->ctrl->regs; u32 reg; /* Change SPI clock to correct frequency, PLLP_OUT0 source */ - clock_start_periph_pll(spi->periph_id, CLOCK_ID_PERIPH, spi->freq); + clock_start_periph_pll(spi->ctrl->periph_id, CLOCK_ID_PERIPH, + spi->ctrl->freq); /* Clear stale status here */ reg = SPI_STAT_RDY | SPI_STAT_RXF_FLUSH | SPI_STAT_TXF_FLUSH | \ SPI_STAT_RXF_UNR | SPI_STAT_TXF_OVF; writel(reg, ®s->status); - debug("spi_init: STATUS = %08x\n", readl(®s->status)); + debug("%s: STATUS = %08x\n", __func__, readl(®s->status)); /* * Use sw-controlled CS, so we can clock in data after ReadID, etc. */ - reg = (spi->mode & 1) << SPI_CMD_ACTIVE_SDA_SHIFT; - if (spi->mode & 2) + reg = (spi->ctrl->mode & 1) << SPI_CMD_ACTIVE_SDA_SHIFT; + if (spi->ctrl->mode & 2) reg |= 1 << SPI_CMD_ACTIVE_SCLK_SHIFT; clrsetbits_le32(®s->command, SPI_CMD_ACTIVE_SCLK_MASK | SPI_CMD_ACTIVE_SDA_MASK, SPI_CMD_CS_SOFT | reg); - debug("spi_init: COMMAND = %08x\n", readl(®s->command)); + debug("%s: COMMAND = %08x\n", __func__, readl(®s->command)); /* * SPI pins on Tegra20 are muxed - change pinmux later due to UART @@ -175,58 +228,34 @@ int spi_claim_bus(struct spi_slave *slave) */ pinmux_set_func(PINGRP_GMD, PMUX_FUNC_SFLASH); pinmux_tristate_disable(PINGRP_LSPI); + pinmux_set_func(PINGRP_GMC, PMUX_FUNC_SFLASH); -#ifndef CONFIG_SPI_UART_SWITCH - /* - * NOTE: - * Only set PinMux bits 3:2 to SPI here on boards that don't have the - * SPI UART switch or subsequent UART data won't go out! See - * spi_uart_switch(). - */ - /* TODO: pinmux_set_func(PINGRP_GMC, PMUX_FUNC_SFLASH); */ -#endif return 0; } -void spi_release_bus(struct spi_slave *slave) -{ - /* - * We can't release UART_DISABLE and set pinmux to UART4 here since - * some code (e,g, spi_flash_probe) uses printf() while the SPI - * bus is held. That is arguably bad, but it has the advantage of - * already being in the source tree. - */ -} - -void spi_cs_activate(struct spi_slave *slave) +void tegra20_spi_cs_activate(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); - - pinmux_select_spi(); + struct spi_regs *regs = spi->ctrl->regs; /* CS is negated on Tegra, so drive a 1 to get a 0 */ - setbits_le32(&spi->regs->command, SPI_CMD_CS_VAL); - - corrupt_delay(); /* Let UART settle */ + setbits_le32(®s->command, SPI_CMD_CS_VAL); } -void spi_cs_deactivate(struct spi_slave *slave) +void tegra20_spi_cs_deactivate(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); - - pinmux_select_uart(); + struct spi_regs *regs = spi->ctrl->regs; /* CS is negated on Tegra, so drive a 0 to get a 1 */ - clrbits_le32(&spi->regs->command, SPI_CMD_CS_VAL); - - corrupt_delay(); /* Let SPI settle */ + clrbits_le32(®s->command, SPI_CMD_CS_VAL); } -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, +int tegra20_spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out, void *data_in, unsigned long flags) { struct tegra_spi_slave *spi = to_tegra_spi(slave); - struct spi_tegra *regs = spi->regs; + struct spi_regs *regs = spi->ctrl->regs; u32 reg, tmpdout, tmpdin = 0; const u8 *dout = data_out; u8 *din = data_in; diff --git a/drivers/spi/tegra_slink.c b/drivers/spi/tegra20_slink.c index 2c41fab..664de6e 100644 --- a/drivers/spi/tegra_slink.c +++ b/drivers/spi/tegra20_slink.c @@ -27,14 +27,68 @@ #include <asm/gpio.h> #include <asm/arch/clock.h> #include <asm/arch-tegra/clk_rst.h> -#include <asm/arch-tegra/tegra_slink.h> +#include <asm/arch-tegra20/tegra20_slink.h> #include <spi.h> #include <fdtdec.h> DECLARE_GLOBAL_DATA_PTR; +/* COMMAND */ +#define SLINK_CMD_ENB (1 << 31) +#define SLINK_CMD_GO (1 << 30) +#define SLINK_CMD_M_S (1 << 28) +#define SLINK_CMD_CK_SDA (1 << 21) +#define SLINK_CMD_CS_POL (1 << 13) +#define SLINK_CMD_CS_VAL (1 << 12) +#define SLINK_CMD_CS_SOFT (1 << 11) +#define SLINK_CMD_BIT_LENGTH (1 << 4) +#define SLINK_CMD_BIT_LENGTH_MASK 0x0000001F +/* COMMAND2 */ +#define SLINK_CMD2_TXEN (1 << 30) +#define SLINK_CMD2_RXEN (1 << 31) +#define SLINK_CMD2_SS_EN (1 << 18) +#define SLINK_CMD2_SS_EN_SHIFT 18 +#define SLINK_CMD2_SS_EN_MASK 0x000C0000 +#define SLINK_CMD2_CS_ACTIVE_BETWEEN (1 << 17) +/* STATUS */ +#define SLINK_STAT_BSY (1 << 31) +#define SLINK_STAT_RDY (1 << 30) +#define SLINK_STAT_ERR (1 << 29) +#define SLINK_STAT_RXF_FLUSH (1 << 27) +#define SLINK_STAT_TXF_FLUSH (1 << 26) +#define SLINK_STAT_RXF_OVF (1 << 25) +#define SLINK_STAT_TXF_UNR (1 << 24) +#define SLINK_STAT_RXF_EMPTY (1 << 23) +#define SLINK_STAT_RXF_FULL (1 << 22) +#define SLINK_STAT_TXF_EMPTY (1 << 21) +#define SLINK_STAT_TXF_FULL (1 << 20) +#define SLINK_STAT_TXF_OVF (1 << 19) +#define SLINK_STAT_RXF_UNR (1 << 18) +#define SLINK_STAT_CUR_BLKCNT (1 << 15) +/* STATUS2 */ +#define SLINK_STAT2_RXF_FULL_CNT (1 << 16) +#define SLINK_STAT2_TXF_FULL_CNT (1 << 0) + +#define SPI_TIMEOUT 1000 +#define TEGRA_SPI_MAX_FREQ 52000000 + +struct spi_regs { + u32 command; /* SLINK_COMMAND_0 register */ + u32 command2; /* SLINK_COMMAND2_0 reg */ + u32 status; /* SLINK_STATUS_0 register */ + u32 reserved; /* Reserved offset 0C */ + u32 mas_data; /* SLINK_MAS_DATA_0 reg */ + u32 slav_data; /* SLINK_SLAVE_DATA_0 reg */ + u32 dma_ctl; /* SLINK_DMA_CTL_0 register */ + u32 status2; /* SLINK_STATUS2_0 reg */ + u32 rsvd[56]; /* 0x20 to 0xFF reserved */ + u32 tx_fifo; /* SLINK_TX_FIFO_0 reg off 100h */ + u32 rsvd2[31]; /* 0x104 to 0x17F reserved */ + u32 rx_fifo; /* SLINK_RX_FIFO_0 reg off 180h */ +}; + struct tegra_spi_ctrl { - struct slink_tegra *regs; + struct spi_regs *regs; unsigned int freq; unsigned int mode; int periph_id; @@ -53,7 +107,7 @@ static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave) return container_of(slave, struct tegra_spi_slave, slave); } -int spi_cs_is_valid(unsigned int bus, unsigned int cs) +int tegra30_spi_cs_is_valid(unsigned int bus, unsigned int cs) { if (bus >= CONFIG_TEGRA_SLINK_CTRLS || cs > 3 || !spi_ctrls[bus].valid) return 0; @@ -61,7 +115,7 @@ int spi_cs_is_valid(unsigned int bus, unsigned int cs) return 1; } -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, +struct spi_slave *tegra30_spi_setup_slave(unsigned int bus, unsigned int cs, unsigned int max_hz, unsigned int mode) { struct tegra_spi_slave *spi; @@ -81,13 +135,11 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, return NULL; } - spi = malloc(sizeof(struct tegra_spi_slave)); + spi = spi_alloc_slave(struct tegra_spi_slave, bus, cs); if (!spi) { printf("SPI error: malloc of SPI structure failed\n"); return NULL; } - spi->slave.bus = bus; - spi->slave.cs = cs; spi->ctrl = &spi_ctrls[bus]; if (!spi->ctrl) { printf("SPI error: could not find controller for bus %d\n", @@ -105,32 +157,26 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, return &spi->slave; } -void spi_free_slave(struct spi_slave *slave) +void tegra30_spi_free_slave(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); free(spi); } -void spi_init(void) +int tegra30_spi_init(int *node_list, int count) { struct tegra_spi_ctrl *ctrl; int i; -#ifdef CONFIG_OF_CONTROL int node = 0; - int count; - int node_list[CONFIG_TEGRA_SLINK_CTRLS]; + int found = 0; - count = fdtdec_find_aliases_for_id(gd->fdt_blob, "spi", - COMPAT_NVIDIA_TEGRA20_SLINK, - node_list, - CONFIG_TEGRA_SLINK_CTRLS); for (i = 0; i < count; i++) { ctrl = &spi_ctrls[i]; node = node_list[i]; - ctrl->regs = (struct slink_tegra *)fdtdec_get_addr(gd->fdt_blob, - node, "reg"); + ctrl->regs = (struct spi_regs *)fdtdec_get_addr(gd->fdt_blob, + node, "reg"); if ((fdt_addr_t)ctrl->regs == FDT_ADDR_T_NONE) { debug("%s: no slink register found\n", __func__); continue; @@ -148,44 +194,18 @@ void spi_init(void) continue; } ctrl->valid = 1; + found = 1; debug("%s: found controller at %p, freq = %u, periph_id = %d\n", __func__, ctrl->regs, ctrl->freq, ctrl->periph_id); } -#else - for (i = 0; i < CONFIG_TEGRA_SLINK_CTRLS; i++) { - ctrl = &spi_ctrls[i]; - u32 base_regs[] = { - NV_PA_SLINK1_BASE, - NV_PA_SLINK2_BASE, - NV_PA_SLINK3_BASE, - NV_PA_SLINK4_BASE, - NV_PA_SLINK5_BASE, - NV_PA_SLINK6_BASE, - }; - int periph_ids[] = { - PERIPH_ID_SBC1, - PERIPH_ID_SBC2, - PERIPH_ID_SBC3, - PERIPH_ID_SBC4, - PERIPH_ID_SBC5, - PERIPH_ID_SBC6, - }; - ctrl->regs = (struct slink_tegra *)base_regs[i]; - ctrl->freq = TEGRA_SPI_MAX_FREQ; - ctrl->periph_id = periph_ids[i]; - ctrl->valid = 1; - - debug("%s: found controller at %p, freq = %u, periph_id = %d\n", - __func__, ctrl->regs, ctrl->freq, ctrl->periph_id); - } -#endif + return !found; } -int spi_claim_bus(struct spi_slave *slave) +int tegra30_spi_claim_bus(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); - struct slink_tegra *regs = spi->ctrl->regs; + struct spi_regs *regs = spi->ctrl->regs; u32 reg; /* Change SPI clock to correct frequency, PLLP_OUT0 source */ @@ -207,33 +227,29 @@ int spi_claim_bus(struct spi_slave *slave) return 0; } -void spi_release_bus(struct spi_slave *slave) -{ -} - -void spi_cs_activate(struct spi_slave *slave) +void tegra30_spi_cs_activate(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); - struct slink_tegra *regs = spi->ctrl->regs; + struct spi_regs *regs = spi->ctrl->regs; /* CS is negated on Tegra, so drive a 1 to get a 0 */ setbits_le32(®s->command, SLINK_CMD_CS_VAL); } -void spi_cs_deactivate(struct spi_slave *slave) +void tegra30_spi_cs_deactivate(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); - struct slink_tegra *regs = spi->ctrl->regs; + struct spi_regs *regs = spi->ctrl->regs; /* CS is negated on Tegra, so drive a 0 to get a 1 */ clrbits_le32(®s->command, SLINK_CMD_CS_VAL); } -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, +int tegra30_spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out, void *data_in, unsigned long flags) { struct tegra_spi_slave *spi = to_tegra_spi(slave); - struct slink_tegra *regs = spi->ctrl->regs; + struct spi_regs *regs = spi->ctrl->regs; u32 reg, tmpdout, tmpdin = 0; const u8 *dout = data_out; u8 *din = data_in; diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index db01cc2..a82b056 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c @@ -85,14 +85,12 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, return NULL; } - xilspi = malloc(sizeof(*xilspi)); + xilspi = spi_alloc_slave(struct xilinx_spi_slave, bus, cs); if (!xilspi) { printf("XILSPI error: %s: malloc of SPI structure failed\n", __func__); return NULL; } - xilspi->slave.bus = bus; - xilspi->slave.cs = cs; xilspi->regs = (struct xilinx_spi_reg *)xilinx_spi_base_list[bus]; xilspi->freq = max_hz; xilspi->mode = mode; diff --git a/drivers/usb/eth/smsc95xx.c b/drivers/usb/eth/smsc95xx.c index dc5ca65..fd8f8a7 100644 --- a/drivers/usb/eth/smsc95xx.c +++ b/drivers/usb/eth/smsc95xx.c @@ -265,10 +265,6 @@ static int smsc95xx_eeprom_confirm_not_busy(struct ueth_data *dev) do { smsc95xx_read_reg(dev, E2P_CMD, &val); - if (!(val & E2P_CMD_LOADED_)) { - debug("No EEPROM present\n"); - return -1; - } if (!(val & E2P_CMD_BUSY_)) return 0; udelay(40); diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 040eaba..e545b6b 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -25,15 +25,21 @@ include $(TOPDIR)/config.mk LIB := $(obj)libusb_gadget.o +# if defined(CONFIG_USB_GADGET) || defined(CONFIG_USB_ETHER) +# Everytime you forget how crufty makefiles can get things like +# this remind you... +ifneq (,$(CONFIG_USB_GADGET)$(CONFIG_USB_ETHER)) +COBJS-y += epautoconf.o config.o usbstring.o +endif + # new USB gadget layer dependencies ifdef CONFIG_USB_GADGET -COBJS-y += epautoconf.o config.o usbstring.o COBJS-$(CONFIG_USB_GADGET_S3C_UDC_OTG) += s3c_udc_otg.o COBJS-$(CONFIG_USBDOWNLOAD_GADGET) += g_dnl.o COBJS-$(CONFIG_DFU_FUNCTION) += f_dfu.o endif ifdef CONFIG_USB_ETHER -COBJS-y += ether.o epautoconf.o config.o usbstring.o +COBJS-y += ether.o COBJS-$(CONFIG_USB_ETH_RNDIS) += rndis.o COBJS-$(CONFIG_MV_UDC) += mv_udc.o COBJS-$(CONFIG_CPU_PXA25X) += pxa25x_udc.o diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index ebb5131..2c5600e 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -859,6 +859,25 @@ unknown: if (&f->list == &cdev->config->functions) f = NULL; break; + /* + * dfu-util (version 0.5) sets bmRequestType.Receipent = Device + * for non-standard request (w_value = 0x21, + * bRequest = GET_DESCRIPTOR in this case). + * When only one interface is registered (as it is done now), + * then this request shall be handled as it was requested for + * interface. + * + * In the below code it is checked if only one interface is + * present and proper function for it is extracted. Due to that + * function's setup (f->setup) is called to handle this + * special non-standard request. + */ + case USB_RECIP_DEVICE: + debug("cdev->config->next_interface_id: %d intf: %d\n", + cdev->config->next_interface_id, intf); + if (cdev->config->next_interface_id == 1) + f = cdev->config->interface[intf]; + break; } if (f && f->setup) diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c index 10547e3..a322ae5 100644 --- a/drivers/usb/gadget/f_dfu.c +++ b/drivers/usb/gadget/f_dfu.c @@ -164,6 +164,9 @@ static void handle_getstatus(struct usb_request *req) /* send status response */ dstat->bStatus = f_dfu->dfu_status; + dstat->bwPollTimeout[0] = 0; + dstat->bwPollTimeout[1] = 0; + dstat->bwPollTimeout[2] = 0; dstat->bState = f_dfu->dfu_state; dstat->iString = 0; } diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c new file mode 100644 index 0000000..c28866f --- /dev/null +++ b/drivers/usb/gadget/f_mass_storage.c @@ -0,0 +1,2793 @@ +/* + * f_mass_storage.c -- Mass Storage USB Composite Function + * + * Copyright (C) 2003-2008 Alan Stern + * Copyright (C) 2009 Samsung Electronics + * Author: Michal Nazarewicz <m.nazarewicz@samsung.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/* + * The Mass Storage Function acts as a USB Mass Storage device, + * appearing to the host as a disk drive or as a CD-ROM drive. In + * addition to providing an example of a genuinely useful composite + * function for a USB device, it also illustrates a technique of + * double-buffering for increased throughput. + * + * Function supports multiple logical units (LUNs). Backing storage + * for each LUN is provided by a regular file or a block device. + * Access for each LUN can be limited to read-only. Moreover, the + * function can indicate that LUN is removable and/or CD-ROM. (The + * later implies read-only access.) + * + * MSF is configured by specifying a fsg_config structure. It has the + * following fields: + * + * nluns Number of LUNs function have (anywhere from 1 + * to FSG_MAX_LUNS which is 8). + * luns An array of LUN configuration values. This + * should be filled for each LUN that + * function will include (ie. for "nluns" + * LUNs). Each element of the array has + * the following fields: + * ->filename The path to the backing file for the LUN. + * Required if LUN is not marked as + * removable. + * ->ro Flag specifying access to the LUN shall be + * read-only. This is implied if CD-ROM + * emulation is enabled as well as when + * it was impossible to open "filename" + * in R/W mode. + * ->removable Flag specifying that LUN shall be indicated as + * being removable. + * ->cdrom Flag specifying that LUN shall be reported as + * being a CD-ROM. + * + * lun_name_format A printf-like format for names of the LUN + * devices. This determines how the + * directory in sysfs will be named. + * Unless you are using several MSFs in + * a single gadget (as opposed to single + * MSF in many configurations) you may + * leave it as NULL (in which case + * "lun%d" will be used). In the format + * you can use "%d" to index LUNs for + * MSF's with more than one LUN. (Beware + * that there is only one integer given + * as an argument for the format and + * specifying invalid format may cause + * unspecified behaviour.) + * thread_name Name of the kernel thread process used by the + * MSF. You can safely set it to NULL + * (in which case default "file-storage" + * will be used). + * + * vendor_name + * product_name + * release Information used as a reply to INQUIRY + * request. To use default set to NULL, + * NULL, 0xffff respectively. The first + * field should be 8 and the second 16 + * characters or less. + * + * can_stall Set to permit function to halt bulk endpoints. + * Disabled on some USB devices known not + * to work correctly. You should set it + * to true. + * + * If "removable" is not set for a LUN then a backing file must be + * specified. If it is set, then NULL filename means the LUN's medium + * is not loaded (an empty string as "filename" in the fsg_config + * structure causes error). The CD-ROM emulation includes a single + * data track and no audio tracks; hence there need be only one + * backing file per LUN. Note also that the CD-ROM block length is + * set to 512 rather than the more common value 2048. + * + * + * MSF includes support for module parameters. If gadget using it + * decides to use it, the following module parameters will be + * available: + * + * file=filename[,filename...] + * Names of the files or block devices used for + * backing storage. + * ro=b[,b...] Default false, boolean for read-only access. + * removable=b[,b...] + * Default true, boolean for removable media. + * cdrom=b[,b...] Default false, boolean for whether to emulate + * a CD-ROM drive. + * luns=N Default N = number of filenames, number of + * LUNs to support. + * stall Default determined according to the type of + * USB device controller (usually true), + * boolean to permit the driver to halt + * bulk endpoints. + * + * The module parameters may be prefixed with some string. You need + * to consult gadget's documentation or source to verify whether it is + * using those module parameters and if it does what are the prefixes + * (look for FSG_MODULE_PARAMETERS() macro usage, what's inside it is + * the prefix). + * + * + * Requirements are modest; only a bulk-in and a bulk-out endpoint are + * needed. The memory requirement amounts to two 16K buffers, size + * configurable by a parameter. Support is included for both + * full-speed and high-speed operation. + * + * Note that the driver is slightly non-portable in that it assumes a + * single memory/DMA buffer will be useable for bulk-in, bulk-out, and + * interrupt-in endpoints. With most device controllers this isn't an + * issue, but there may be some with hardware restrictions that prevent + * a buffer from being used by more than one endpoint. + * + * + * The pathnames of the backing files and the ro settings are + * available in the attribute files "file" and "ro" in the lun<n> (or + * to be more precise in a directory which name comes from + * "lun_name_format" option!) subdirectory of the gadget's sysfs + * directory. If the "removable" option is set, writing to these + * files will simulate ejecting/loading the medium (writing an empty + * line means eject) and adjusting a write-enable tab. Changes to the + * ro setting are not allowed when the medium is loaded or if CD-ROM + * emulation is being used. + * + * When a LUN receive an "eject" SCSI request (Start/Stop Unit), + * if the LUN is removable, the backing file is released to simulate + * ejection. + * + * + * This function is heavily based on "File-backed Storage Gadget" by + * Alan Stern which in turn is heavily based on "Gadget Zero" by David + * Brownell. The driver's SCSI command interface was based on the + * "Information technology - Small Computer System Interface - 2" + * document from X3T9.2 Project 375D, Revision 10L, 7-SEP-93, + * available at <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>. + * The single exception is opcode 0x23 (READ FORMAT CAPACITIES), which + * was based on the "Universal Serial Bus Mass Storage Class UFI + * Command Specification" document, Revision 1.0, December 14, 1998, + * available at + * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>. + */ + + +/* + * Driver Design + * + * The MSF is fairly straightforward. There is a main kernel + * thread that handles most of the work. Interrupt routines field + * callbacks from the controller driver: bulk- and interrupt-request + * completion notifications, endpoint-0 events, and disconnect events. + * Completion events are passed to the main thread by wakeup calls. Many + * ep0 requests are handled at interrupt time, but SetInterface, + * SetConfiguration, and device reset requests are forwarded to the + * thread in the form of "exceptions" using SIGUSR1 signals (since they + * should interrupt any ongoing file I/O operations). + * + * The thread's main routine implements the standard command/data/status + * parts of a SCSI interaction. It and its subroutines are full of tests + * for pending signals/exceptions -- all this polling is necessary since + * the kernel has no setjmp/longjmp equivalents. (Maybe this is an + * indication that the driver really wants to be running in userspace.) + * An important point is that so long as the thread is alive it keeps an + * open reference to the backing file. This will prevent unmounting + * the backing file's underlying filesystem and could cause problems + * during system shutdown, for example. To prevent such problems, the + * thread catches INT, TERM, and KILL signals and converts them into + * an EXIT exception. + * + * In normal operation the main thread is started during the gadget's + * fsg_bind() callback and stopped during fsg_unbind(). But it can + * also exit when it receives a signal, and there's no point leaving + * the gadget running when the thread is dead. At of this moment, MSF + * provides no way to deregister the gadget when thread dies -- maybe + * a callback functions is needed. + * + * To provide maximum throughput, the driver uses a circular pipeline of + * buffer heads (struct fsg_buffhd). In principle the pipeline can be + * arbitrarily long; in practice the benefits don't justify having more + * than 2 stages (i.e., double buffering). But it helps to think of the + * pipeline as being a long one. Each buffer head contains a bulk-in and + * a bulk-out request pointer (since the buffer can be used for both + * output and input -- directions always are given from the host's + * point of view) as well as a pointer to the buffer and various state + * variables. + * + * Use of the pipeline follows a simple protocol. There is a variable + * (fsg->next_buffhd_to_fill) that points to the next buffer head to use. + * At any time that buffer head may still be in use from an earlier + * request, so each buffer head has a state variable indicating whether + * it is EMPTY, FULL, or BUSY. Typical use involves waiting for the + * buffer head to be EMPTY, filling the buffer either by file I/O or by + * USB I/O (during which the buffer head is BUSY), and marking the buffer + * head FULL when the I/O is complete. Then the buffer will be emptied + * (again possibly by USB I/O, during which it is marked BUSY) and + * finally marked EMPTY again (possibly by a completion routine). + * + * A module parameter tells the driver to avoid stalling the bulk + * endpoints wherever the transport specification allows. This is + * necessary for some UDCs like the SuperH, which cannot reliably clear a + * halt on a bulk endpoint. However, under certain circumstances the + * Bulk-only specification requires a stall. In such cases the driver + * will halt the endpoint and set a flag indicating that it should clear + * the halt in software during the next device reset. Hopefully this + * will permit everything to work correctly. Furthermore, although the + * specification allows the bulk-out endpoint to halt when the host sends + * too much data, implementing this would cause an unavoidable race. + * The driver will always use the "no-stall" approach for OUT transfers. + * + * One subtle point concerns sending status-stage responses for ep0 + * requests. Some of these requests, such as device reset, can involve + * interrupting an ongoing file I/O operation, which might take an + * arbitrarily long time. During that delay the host might give up on + * the original ep0 request and issue a new one. When that happens the + * driver should not notify the host about completion of the original + * request, as the host will no longer be waiting for it. So the driver + * assigns to each ep0 request a unique tag, and it keeps track of the + * tag value of the request associated with a long-running exception + * (device-reset, interface-change, or configuration-change). When the + * exception handler is finished, the status-stage response is submitted + * only if the current ep0 request tag is equal to the exception request + * tag. Thus only the most recently received ep0 request will get a + * status-stage response. + * + * Warning: This driver source file is too long. It ought to be split up + * into a header file plus about 3 separate .c files, to handle the details + * of the Gadget, USB Mass Storage, and SCSI protocols. + */ + +/* #define VERBOSE_DEBUG */ +/* #define DUMP_MSGS */ + +#include <config.h> +#include <malloc.h> +#include <common.h> + +#include <linux/err.h> +#include <linux/usb/ch9.h> +#include <linux/usb/gadget.h> +#include <usb_mass_storage.h> + +#include <asm/unaligned.h> +#include <linux/usb/gadget.h> +#include <linux/usb/gadget.h> +#include <linux/usb/composite.h> +#include <usb/lin_gadget_compat.h> + +/*------------------------------------------------------------------------*/ + +#define FSG_DRIVER_DESC "Mass Storage Function" +#define FSG_DRIVER_VERSION "2012/06/5" + +static const char fsg_string_interface[] = "Mass Storage"; + + +#define FSG_NO_INTR_EP 1 +#define FSG_NO_DEVICE_STRINGS 1 +#define FSG_NO_OTG 1 +#define FSG_NO_INTR_EP 1 + +#include "storage_common.c" + +/*-------------------------------------------------------------------------*/ + +#define GFP_ATOMIC ((gfp_t) 0) +#define PAGE_CACHE_SHIFT 12 +#define PAGE_CACHE_SIZE (1 << PAGE_CACHE_SHIFT) +#define kthread_create(...) __builtin_return_address(0) +#define wait_for_completion(...) do {} while (0) + +struct kref {int x; }; +struct completion {int x; }; + +inline void set_bit(int nr, volatile void *addr) +{ + int mask; + unsigned int *a = (unsigned int *) addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + *a |= mask; +} + +inline void clear_bit(int nr, volatile void *addr) +{ + int mask; + unsigned int *a = (unsigned int *) addr; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + *a &= ~mask; +} + +struct fsg_dev; +struct fsg_common; + +/* Data shared by all the FSG instances. */ +struct fsg_common { + struct usb_gadget *gadget; + struct fsg_dev *fsg, *new_fsg; + + struct usb_ep *ep0; /* Copy of gadget->ep0 */ + struct usb_request *ep0req; /* Copy of cdev->req */ + unsigned int ep0_req_tag; + + struct fsg_buffhd *next_buffhd_to_fill; + struct fsg_buffhd *next_buffhd_to_drain; + struct fsg_buffhd buffhds[FSG_NUM_BUFFERS]; + + int cmnd_size; + u8 cmnd[MAX_COMMAND_SIZE]; + + unsigned int nluns; + unsigned int lun; + struct fsg_lun luns[FSG_MAX_LUNS]; + + unsigned int bulk_out_maxpacket; + enum fsg_state state; /* For exception handling */ + unsigned int exception_req_tag; + + enum data_direction data_dir; + u32 data_size; + u32 data_size_from_cmnd; + u32 tag; + u32 residue; + u32 usb_amount_left; + + unsigned int can_stall:1; + unsigned int free_storage_on_release:1; + unsigned int phase_error:1; + unsigned int short_packet_received:1; + unsigned int bad_lun_okay:1; + unsigned int running:1; + + int thread_wakeup_needed; + struct completion thread_notifier; + struct task_struct *thread_task; + + /* Callback functions. */ + const struct fsg_operations *ops; + /* Gadget's private data. */ + void *private_data; + + const char *vendor_name; /* 8 characters or less */ + const char *product_name; /* 16 characters or less */ + u16 release; + + /* Vendor (8 chars), product (16 chars), release (4 + * hexadecimal digits) and NUL byte */ + char inquiry_string[8 + 16 + 4 + 1]; + + struct kref ref; +}; + +struct fsg_config { + unsigned nluns; + struct fsg_lun_config { + const char *filename; + char ro; + char removable; + char cdrom; + char nofua; + } luns[FSG_MAX_LUNS]; + + /* Callback functions. */ + const struct fsg_operations *ops; + /* Gadget's private data. */ + void *private_data; + + const char *vendor_name; /* 8 characters or less */ + const char *product_name; /* 16 characters or less */ + + char can_stall; +}; + +struct fsg_dev { + struct usb_function function; + struct usb_gadget *gadget; /* Copy of cdev->gadget */ + struct fsg_common *common; + + u16 interface_number; + + unsigned int bulk_in_enabled:1; + unsigned int bulk_out_enabled:1; + + unsigned long atomic_bitflags; +#define IGNORE_BULK_OUT 0 + + struct usb_ep *bulk_in; + struct usb_ep *bulk_out; +}; + + +static inline int __fsg_is_set(struct fsg_common *common, + const char *func, unsigned line) +{ + if (common->fsg) + return 1; + ERROR(common, "common->fsg is NULL in %s at %u\n", func, line); + WARN_ON(1); + return 0; +} + +#define fsg_is_set(common) likely(__fsg_is_set(common, __func__, __LINE__)) + + +static inline struct fsg_dev *fsg_from_func(struct usb_function *f) +{ + return container_of(f, struct fsg_dev, function); +} + + +typedef void (*fsg_routine_t)(struct fsg_dev *); + +static int exception_in_progress(struct fsg_common *common) +{ + return common->state > FSG_STATE_IDLE; +} + +/* Make bulk-out requests be divisible by the maxpacket size */ +static void set_bulk_out_req_length(struct fsg_common *common, + struct fsg_buffhd *bh, unsigned int length) +{ + unsigned int rem; + + bh->bulk_out_intended_length = length; + rem = length % common->bulk_out_maxpacket; + if (rem > 0) + length += common->bulk_out_maxpacket - rem; + bh->outreq->length = length; +} + +/*-------------------------------------------------------------------------*/ + +struct ums_board_info *ums_info; +struct fsg_common *the_fsg_common; + +static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) +{ + const char *name; + + if (ep == fsg->bulk_in) + name = "bulk-in"; + else if (ep == fsg->bulk_out) + name = "bulk-out"; + else + name = ep->name; + DBG(fsg, "%s set halt\n", name); + return usb_ep_set_halt(ep); +} + +/*-------------------------------------------------------------------------*/ + +/* These routines may be called in process context or in_irq */ + +/* Caller must hold fsg->lock */ +static void wakeup_thread(struct fsg_common *common) +{ + common->thread_wakeup_needed = 1; +} + +static void raise_exception(struct fsg_common *common, enum fsg_state new_state) +{ + /* Do nothing if a higher-priority exception is already in progress. + * If a lower-or-equal priority exception is in progress, preempt it + * and notify the main thread by sending it a signal. */ + if (common->state <= new_state) { + common->exception_req_tag = common->ep0_req_tag; + common->state = new_state; + common->thread_wakeup_needed = 1; + } +} + +/*-------------------------------------------------------------------------*/ + +static int ep0_queue(struct fsg_common *common) +{ + int rc; + + rc = usb_ep_queue(common->ep0, common->ep0req, GFP_ATOMIC); + common->ep0->driver_data = common; + if (rc != 0 && rc != -ESHUTDOWN) { + /* We can't do much more than wait for a reset */ + WARNING(common, "error in submission: %s --> %d\n", + common->ep0->name, rc); + } + return rc; +} + +/*-------------------------------------------------------------------------*/ + +/* Bulk and interrupt endpoint completion handlers. + * These always run in_irq. */ + +static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct fsg_common *common = ep->driver_data; + struct fsg_buffhd *bh = req->context; + + if (req->status || req->actual != req->length) + DBG(common, "%s --> %d, %u/%u\n", __func__, + req->status, req->actual, req->length); + if (req->status == -ECONNRESET) /* Request was cancelled */ + usb_ep_fifo_flush(ep); + + /* Hold the lock while we update the request and buffer states */ + bh->inreq_busy = 0; + bh->state = BUF_STATE_EMPTY; + wakeup_thread(common); +} + +static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct fsg_common *common = ep->driver_data; + struct fsg_buffhd *bh = req->context; + + dump_msg(common, "bulk-out", req->buf, req->actual); + if (req->status || req->actual != bh->bulk_out_intended_length) + DBG(common, "%s --> %d, %u/%u\n", __func__, + req->status, req->actual, + bh->bulk_out_intended_length); + if (req->status == -ECONNRESET) /* Request was cancelled */ + usb_ep_fifo_flush(ep); + + /* Hold the lock while we update the request and buffer states */ + bh->outreq_busy = 0; + bh->state = BUF_STATE_FULL; + wakeup_thread(common); +} + +/*-------------------------------------------------------------------------*/ + +/* Ep0 class-specific handlers. These always run in_irq. */ + +static int fsg_setup(struct usb_function *f, + const struct usb_ctrlrequest *ctrl) +{ + struct fsg_dev *fsg = fsg_from_func(f); + struct usb_request *req = fsg->common->ep0req; + u16 w_index = le16_to_cpu(ctrl->wIndex); + u16 w_value = le16_to_cpu(ctrl->wValue); + u16 w_length = le16_to_cpu(ctrl->wLength); + + if (!fsg_is_set(fsg->common)) + return -EOPNOTSUPP; + + switch (ctrl->bRequest) { + + case USB_BULK_RESET_REQUEST: + if (ctrl->bRequestType != + (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) + break; + if (w_index != fsg->interface_number || w_value != 0) + return -EDOM; + + /* Raise an exception to stop the current operation + * and reinitialize our state. */ + DBG(fsg, "bulk reset request\n"); + raise_exception(fsg->common, FSG_STATE_RESET); + return DELAYED_STATUS; + + case USB_BULK_GET_MAX_LUN_REQUEST: + if (ctrl->bRequestType != + (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) + break; + if (w_index != fsg->interface_number || w_value != 0) + return -EDOM; + VDBG(fsg, "get max LUN\n"); + *(u8 *) req->buf = fsg->common->nluns - 1; + + /* Respond with data/status */ + req->length = min((u16)1, w_length); + return ep0_queue(fsg->common); + } + + VDBG(fsg, + "unknown class-specific control req " + "%02x.%02x v%04x i%04x l%u\n", + ctrl->bRequestType, ctrl->bRequest, + le16_to_cpu(ctrl->wValue), w_index, w_length); + return -EOPNOTSUPP; +} + +/*-------------------------------------------------------------------------*/ + +/* All the following routines run in process context */ + +/* Use this for bulk or interrupt transfers, not ep0 */ +static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep, + struct usb_request *req, int *pbusy, + enum fsg_buffer_state *state) +{ + int rc; + + if (ep == fsg->bulk_in) + dump_msg(fsg, "bulk-in", req->buf, req->length); + + *pbusy = 1; + *state = BUF_STATE_BUSY; + rc = usb_ep_queue(ep, req, GFP_KERNEL); + if (rc != 0) { + *pbusy = 0; + *state = BUF_STATE_EMPTY; + + /* We can't do much more than wait for a reset */ + + /* Note: currently the net2280 driver fails zero-length + * submissions if DMA is enabled. */ + if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP && + req->length == 0)) + WARNING(fsg, "error in submission: %s --> %d\n", + ep->name, rc); + } +} + +#define START_TRANSFER_OR(common, ep_name, req, pbusy, state) \ + if (fsg_is_set(common)) \ + start_transfer((common)->fsg, (common)->fsg->ep_name, \ + req, pbusy, state); \ + else + +#define START_TRANSFER(common, ep_name, req, pbusy, state) \ + START_TRANSFER_OR(common, ep_name, req, pbusy, state) (void)0 + +static void busy_indicator(void) +{ + static int state; + + switch (state) { + case 0: + puts("\r|"); break; + case 1: + puts("\r/"); break; + case 2: + puts("\r-"); break; + case 3: + puts("\r\\"); break; + case 4: + puts("\r|"); break; + case 5: + puts("\r/"); break; + case 6: + puts("\r-"); break; + case 7: + puts("\r\\"); break; + default: + state = 0; + } + if (state++ == 8) + state = 0; +} + +static int sleep_thread(struct fsg_common *common) +{ + int rc = 0; + int i = 0, k = 0; + + /* Wait until a signal arrives or we are woken up */ + for (;;) { + if (common->thread_wakeup_needed) + break; + + if (++i == 50000) { + busy_indicator(); + i = 0; + k++; + } + + usb_gadget_handle_interrupts(); + } + common->thread_wakeup_needed = 0; + return rc; +} + +/*-------------------------------------------------------------------------*/ + +static int do_read(struct fsg_common *common) +{ + struct fsg_lun *curlun = &common->luns[common->lun]; + u32 lba; + struct fsg_buffhd *bh; + int rc; + u32 amount_left; + loff_t file_offset; + unsigned int amount; + unsigned int partial_page; + ssize_t nread; + + /* Get the starting Logical Block Address and check that it's + * not too big */ + if (common->cmnd[0] == SC_READ_6) + lba = get_unaligned_be24(&common->cmnd[1]); + else { + lba = get_unaligned_be32(&common->cmnd[2]); + + /* We allow DPO (Disable Page Out = don't save data in the + * cache) and FUA (Force Unit Access = don't read from the + * cache), but we don't implement them. */ + if ((common->cmnd[1] & ~0x18) != 0) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + } + if (lba >= curlun->num_sectors) { + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + return -EINVAL; + } + file_offset = ((loff_t) lba) << 9; + + /* Carry out the file reads */ + amount_left = common->data_size_from_cmnd; + if (unlikely(amount_left == 0)) + return -EIO; /* No default reply */ + + for (;;) { + + /* Figure out how much we need to read: + * Try to read the remaining amount. + * But don't read more than the buffer size. + * And don't try to read past the end of the file. + * Finally, if we're not at a page boundary, don't read past + * the next page. + * If this means reading 0 then we were asked to read past + * the end of file. */ + amount = min(amount_left, FSG_BUFLEN); + partial_page = file_offset & (PAGE_CACHE_SIZE - 1); + if (partial_page > 0) + amount = min(amount, (unsigned int) PAGE_CACHE_SIZE - + partial_page); + + /* Wait for the next buffer to become available */ + bh = common->next_buffhd_to_fill; + while (bh->state != BUF_STATE_EMPTY) { + rc = sleep_thread(common); + if (rc) + return rc; + } + + /* If we were asked to read past the end of file, + * end with an empty buffer. */ + if (amount == 0) { + curlun->sense_data = + SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + curlun->info_valid = 1; + bh->inreq->length = 0; + bh->state = BUF_STATE_FULL; + break; + } + + /* Perform the read */ + nread = 0; + rc = ums_info->read_sector(&(ums_info->ums_dev), + file_offset / SECTOR_SIZE, + amount / SECTOR_SIZE, + (char __user *)bh->buf); + if (rc) + return -EIO; + nread = amount; + + VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, + (unsigned long long) file_offset, + (int) nread); + + if (nread < 0) { + LDBG(curlun, "error in file read: %d\n", + (int) nread); + nread = 0; + } else if (nread < amount) { + LDBG(curlun, "partial file read: %d/%u\n", + (int) nread, amount); + nread -= (nread & 511); /* Round down to a block */ + } + file_offset += nread; + amount_left -= nread; + common->residue -= nread; + bh->inreq->length = nread; + bh->state = BUF_STATE_FULL; + + /* If an error occurred, report it and its position */ + if (nread < amount) { + curlun->sense_data = SS_UNRECOVERED_READ_ERROR; + curlun->info_valid = 1; + break; + } + + if (amount_left == 0) + break; /* No more left to read */ + + /* Send this buffer and go read some more */ + bh->inreq->zero = 0; + START_TRANSFER_OR(common, bulk_in, bh->inreq, + &bh->inreq_busy, &bh->state) + /* Don't know what to do if + * common->fsg is NULL */ + return -EIO; + common->next_buffhd_to_fill = bh->next; + } + + return -EIO; /* No default reply */ +} + +/*-------------------------------------------------------------------------*/ + +static int do_write(struct fsg_common *common) +{ + struct fsg_lun *curlun = &common->luns[common->lun]; + u32 lba; + struct fsg_buffhd *bh; + int get_some_more; + u32 amount_left_to_req, amount_left_to_write; + loff_t usb_offset, file_offset; + unsigned int amount; + unsigned int partial_page; + ssize_t nwritten; + int rc; + + if (curlun->ro) { + curlun->sense_data = SS_WRITE_PROTECTED; + return -EINVAL; + } + + /* Get the starting Logical Block Address and check that it's + * not too big */ + if (common->cmnd[0] == SC_WRITE_6) + lba = get_unaligned_be24(&common->cmnd[1]); + else { + lba = get_unaligned_be32(&common->cmnd[2]); + + /* We allow DPO (Disable Page Out = don't save data in the + * cache) and FUA (Force Unit Access = write directly to the + * medium). We don't implement DPO; we implement FUA by + * performing synchronous output. */ + if (common->cmnd[1] & ~0x18) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + } + if (lba >= curlun->num_sectors) { + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + return -EINVAL; + } + + /* Carry out the file writes */ + get_some_more = 1; + file_offset = usb_offset = ((loff_t) lba) << 9; + amount_left_to_req = common->data_size_from_cmnd; + amount_left_to_write = common->data_size_from_cmnd; + + while (amount_left_to_write > 0) { + + /* Queue a request for more data from the host */ + bh = common->next_buffhd_to_fill; + if (bh->state == BUF_STATE_EMPTY && get_some_more) { + + /* Figure out how much we want to get: + * Try to get the remaining amount. + * But don't get more than the buffer size. + * And don't try to go past the end of the file. + * If we're not at a page boundary, + * don't go past the next page. + * If this means getting 0, then we were asked + * to write past the end of file. + * Finally, round down to a block boundary. */ + amount = min(amount_left_to_req, FSG_BUFLEN); + partial_page = usb_offset & (PAGE_CACHE_SIZE - 1); + if (partial_page > 0) + amount = min(amount, + (unsigned int) PAGE_CACHE_SIZE - partial_page); + + if (amount == 0) { + get_some_more = 0; + curlun->sense_data = + SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + curlun->info_valid = 1; + continue; + } + amount -= (amount & 511); + if (amount == 0) { + + /* Why were we were asked to transfer a + * partial block? */ + get_some_more = 0; + continue; + } + + /* Get the next buffer */ + usb_offset += amount; + common->usb_amount_left -= amount; + amount_left_to_req -= amount; + if (amount_left_to_req == 0) + get_some_more = 0; + + /* amount is always divisible by 512, hence by + * the bulk-out maxpacket size */ + bh->outreq->length = amount; + bh->bulk_out_intended_length = amount; + bh->outreq->short_not_ok = 1; + START_TRANSFER_OR(common, bulk_out, bh->outreq, + &bh->outreq_busy, &bh->state) + /* Don't know what to do if + * common->fsg is NULL */ + return -EIO; + common->next_buffhd_to_fill = bh->next; + continue; + } + + /* Write the received data to the backing file */ + bh = common->next_buffhd_to_drain; + if (bh->state == BUF_STATE_EMPTY && !get_some_more) + break; /* We stopped early */ + if (bh->state == BUF_STATE_FULL) { + common->next_buffhd_to_drain = bh->next; + bh->state = BUF_STATE_EMPTY; + + /* Did something go wrong with the transfer? */ + if (bh->outreq->status != 0) { + curlun->sense_data = SS_COMMUNICATION_FAILURE; + curlun->info_valid = 1; + break; + } + + amount = bh->outreq->actual; + + /* Perform the write */ + rc = ums_info->write_sector(&(ums_info->ums_dev), + file_offset / SECTOR_SIZE, + amount / SECTOR_SIZE, + (char __user *)bh->buf); + if (rc) + return -EIO; + nwritten = amount; + + VLDBG(curlun, "file write %u @ %llu -> %d\n", amount, + (unsigned long long) file_offset, + (int) nwritten); + + if (nwritten < 0) { + LDBG(curlun, "error in file write: %d\n", + (int) nwritten); + nwritten = 0; + } else if (nwritten < amount) { + LDBG(curlun, "partial file write: %d/%u\n", + (int) nwritten, amount); + nwritten -= (nwritten & 511); + /* Round down to a block */ + } + file_offset += nwritten; + amount_left_to_write -= nwritten; + common->residue -= nwritten; + + /* If an error occurred, report it and its position */ + if (nwritten < amount) { + curlun->sense_data = SS_WRITE_ERROR; + curlun->info_valid = 1; + break; + } + + /* Did the host decide to stop early? */ + if (bh->outreq->actual != bh->outreq->length) { + common->short_packet_received = 1; + break; + } + continue; + } + + /* Wait for something to happen */ + rc = sleep_thread(common); + if (rc) + return rc; + } + + return -EIO; /* No default reply */ +} + +/*-------------------------------------------------------------------------*/ + +static int do_synchronize_cache(struct fsg_common *common) +{ + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static int do_verify(struct fsg_common *common) +{ + struct fsg_lun *curlun = &common->luns[common->lun]; + u32 lba; + u32 verification_length; + struct fsg_buffhd *bh = common->next_buffhd_to_fill; + loff_t file_offset; + u32 amount_left; + unsigned int amount; + ssize_t nread; + int rc; + + /* Get the starting Logical Block Address and check that it's + * not too big */ + lba = get_unaligned_be32(&common->cmnd[2]); + if (lba >= curlun->num_sectors) { + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + return -EINVAL; + } + + /* We allow DPO (Disable Page Out = don't save data in the + * cache) but we don't implement it. */ + if (common->cmnd[1] & ~0x10) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + verification_length = get_unaligned_be16(&common->cmnd[7]); + if (unlikely(verification_length == 0)) + return -EIO; /* No default reply */ + + /* Prepare to carry out the file verify */ + amount_left = verification_length << 9; + file_offset = ((loff_t) lba) << 9; + + /* Write out all the dirty buffers before invalidating them */ + + /* Just try to read the requested blocks */ + while (amount_left > 0) { + + /* Figure out how much we need to read: + * Try to read the remaining amount, but not more than + * the buffer size. + * And don't try to read past the end of the file. + * If this means reading 0 then we were asked to read + * past the end of file. */ + amount = min(amount_left, FSG_BUFLEN); + if (amount == 0) { + curlun->sense_data = + SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + curlun->info_valid = 1; + break; + } + + /* Perform the read */ + nread = 0; + rc = ums_info->read_sector(&(ums_info->ums_dev), + file_offset / SECTOR_SIZE, + amount / SECTOR_SIZE, + (char __user *)bh->buf); + if (rc) + return -EIO; + nread = amount; + + VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, + (unsigned long long) file_offset, + (int) nread); + if (nread < 0) { + LDBG(curlun, "error in file verify: %d\n", + (int) nread); + nread = 0; + } else if (nread < amount) { + LDBG(curlun, "partial file verify: %d/%u\n", + (int) nread, amount); + nread -= (nread & 511); /* Round down to a sector */ + } + if (nread == 0) { + curlun->sense_data = SS_UNRECOVERED_READ_ERROR; + curlun->info_valid = 1; + break; + } + file_offset += nread; + amount_left -= nread; + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static int do_inquiry(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = &common->luns[common->lun]; + static const char vendor_id[] = "Linux "; + u8 *buf = (u8 *) bh->buf; + + if (!curlun) { /* Unsupported LUNs are okay */ + common->bad_lun_okay = 1; + memset(buf, 0, 36); + buf[0] = 0x7f; /* Unsupported, no device-type */ + buf[4] = 31; /* Additional length */ + return 36; + } + + memset(buf, 0, 8); + buf[0] = TYPE_DISK; + buf[2] = 2; /* ANSI SCSI level 2 */ + buf[3] = 2; /* SCSI-2 INQUIRY data format */ + buf[4] = 31; /* Additional length */ + /* No special options */ + sprintf((char *) (buf + 8), "%-8s%-16s%04x", (char*) vendor_id , + ums_info->name, (u16) 0xffff); + + return 36; +} + + +static int do_request_sense(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = &common->luns[common->lun]; + u8 *buf = (u8 *) bh->buf; + u32 sd, sdinfo; + int valid; + + /* + * From the SCSI-2 spec., section 7.9 (Unit attention condition): + * + * If a REQUEST SENSE command is received from an initiator + * with a pending unit attention condition (before the target + * generates the contingent allegiance condition), then the + * target shall either: + * a) report any pending sense data and preserve the unit + * attention condition on the logical unit, or, + * b) report the unit attention condition, may discard any + * pending sense data, and clear the unit attention + * condition on the logical unit for that initiator. + * + * FSG normally uses option a); enable this code to use option b). + */ +#if 0 + if (curlun && curlun->unit_attention_data != SS_NO_SENSE) { + curlun->sense_data = curlun->unit_attention_data; + curlun->unit_attention_data = SS_NO_SENSE; + } +#endif + + if (!curlun) { /* Unsupported LUNs are okay */ + common->bad_lun_okay = 1; + sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; + sdinfo = 0; + valid = 0; + } else { + sd = curlun->sense_data; + valid = curlun->info_valid << 7; + curlun->sense_data = SS_NO_SENSE; + curlun->info_valid = 0; + } + + memset(buf, 0, 18); + buf[0] = valid | 0x70; /* Valid, current error */ + buf[2] = SK(sd); + put_unaligned_be32(sdinfo, &buf[3]); /* Sense information */ + buf[7] = 18 - 8; /* Additional sense length */ + buf[12] = ASC(sd); + buf[13] = ASCQ(sd); + return 18; +} + +static int do_read_capacity(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = &common->luns[common->lun]; + u32 lba = get_unaligned_be32(&common->cmnd[2]); + int pmi = common->cmnd[8]; + u8 *buf = (u8 *) bh->buf; + + /* Check the PMI and LBA fields */ + if (pmi > 1 || (pmi == 0 && lba != 0)) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + put_unaligned_be32(curlun->num_sectors - 1, &buf[0]); + /* Max logical block */ + put_unaligned_be32(512, &buf[4]); /* Block length */ + return 8; +} + +static int do_read_header(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = &common->luns[common->lun]; + int msf = common->cmnd[1] & 0x02; + u32 lba = get_unaligned_be32(&common->cmnd[2]); + u8 *buf = (u8 *) bh->buf; + + if (common->cmnd[1] & ~0x02) { /* Mask away MSF */ + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + if (lba >= curlun->num_sectors) { + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + return -EINVAL; + } + + memset(buf, 0, 8); + buf[0] = 0x01; /* 2048 bytes of user data, rest is EC */ + store_cdrom_address(&buf[4], msf, lba); + return 8; +} + + +static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = &common->luns[common->lun]; + int msf = common->cmnd[1] & 0x02; + int start_track = common->cmnd[6]; + u8 *buf = (u8 *) bh->buf; + + if ((common->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */ + start_track > 1) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + memset(buf, 0, 20); + buf[1] = (20-2); /* TOC data length */ + buf[2] = 1; /* First track number */ + buf[3] = 1; /* Last track number */ + buf[5] = 0x16; /* Data track, copying allowed */ + buf[6] = 0x01; /* Only track is number 1 */ + store_cdrom_address(&buf[8], msf, 0); + + buf[13] = 0x16; /* Lead-out track is data */ + buf[14] = 0xAA; /* Lead-out track number */ + store_cdrom_address(&buf[16], msf, curlun->num_sectors); + + return 20; +} + +static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = &common->luns[common->lun]; + int mscmnd = common->cmnd[0]; + u8 *buf = (u8 *) bh->buf; + u8 *buf0 = buf; + int pc, page_code; + int changeable_values, all_pages; + int valid_page = 0; + int len, limit; + + if ((common->cmnd[1] & ~0x08) != 0) { /* Mask away DBD */ + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + pc = common->cmnd[2] >> 6; + page_code = common->cmnd[2] & 0x3f; + if (pc == 3) { + curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED; + return -EINVAL; + } + changeable_values = (pc == 1); + all_pages = (page_code == 0x3f); + + /* Write the mode parameter header. Fixed values are: default + * medium type, no cache control (DPOFUA), and no block descriptors. + * The only variable value is the WriteProtect bit. We will fill in + * the mode data length later. */ + memset(buf, 0, 8); + if (mscmnd == SC_MODE_SENSE_6) { + buf[2] = (curlun->ro ? 0x80 : 0x00); /* WP, DPOFUA */ + buf += 4; + limit = 255; + } else { /* SC_MODE_SENSE_10 */ + buf[3] = (curlun->ro ? 0x80 : 0x00); /* WP, DPOFUA */ + buf += 8; + limit = 65535; /* Should really be FSG_BUFLEN */ + } + + /* No block descriptors */ + + /* The mode pages, in numerical order. The only page we support + * is the Caching page. */ + if (page_code == 0x08 || all_pages) { + valid_page = 1; + buf[0] = 0x08; /* Page code */ + buf[1] = 10; /* Page length */ + memset(buf+2, 0, 10); /* None of the fields are changeable */ + + if (!changeable_values) { + buf[2] = 0x04; /* Write cache enable, */ + /* Read cache not disabled */ + /* No cache retention priorities */ + put_unaligned_be16(0xffff, &buf[4]); + /* Don't disable prefetch */ + /* Minimum prefetch = 0 */ + put_unaligned_be16(0xffff, &buf[8]); + /* Maximum prefetch */ + put_unaligned_be16(0xffff, &buf[10]); + /* Maximum prefetch ceiling */ + } + buf += 12; + } + + /* Check that a valid page was requested and the mode data length + * isn't too long. */ + len = buf - buf0; + if (!valid_page || len > limit) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + /* Store the mode data length */ + if (mscmnd == SC_MODE_SENSE_6) + buf0[0] = len - 1; + else + put_unaligned_be16(len - 2, buf0); + return len; +} + + +static int do_start_stop(struct fsg_common *common) +{ + struct fsg_lun *curlun = &common->luns[common->lun]; + + if (!curlun) { + return -EINVAL; + } else if (!curlun->removable) { + curlun->sense_data = SS_INVALID_COMMAND; + return -EINVAL; + } + + return 0; +} + +static int do_prevent_allow(struct fsg_common *common) +{ + struct fsg_lun *curlun = &common->luns[common->lun]; + int prevent; + + if (!curlun->removable) { + curlun->sense_data = SS_INVALID_COMMAND; + return -EINVAL; + } + + prevent = common->cmnd[4] & 0x01; + if ((common->cmnd[4] & ~0x01) != 0) { /* Mask away Prevent */ + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + if (curlun->prevent_medium_removal && !prevent) + fsg_lun_fsync_sub(curlun); + curlun->prevent_medium_removal = prevent; + return 0; +} + + +static int do_read_format_capacities(struct fsg_common *common, + struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = &common->luns[common->lun]; + u8 *buf = (u8 *) bh->buf; + + buf[0] = buf[1] = buf[2] = 0; + buf[3] = 8; /* Only the Current/Maximum Capacity Descriptor */ + buf += 4; + + put_unaligned_be32(curlun->num_sectors, &buf[0]); + /* Number of blocks */ + put_unaligned_be32(512, &buf[4]); /* Block length */ + buf[4] = 0x02; /* Current capacity */ + return 12; +} + + +static int do_mode_select(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = &common->luns[common->lun]; + + /* We don't support MODE SELECT */ + if (curlun) + curlun->sense_data = SS_INVALID_COMMAND; + return -EINVAL; +} + + +/*-------------------------------------------------------------------------*/ + +static int halt_bulk_in_endpoint(struct fsg_dev *fsg) +{ + int rc; + + rc = fsg_set_halt(fsg, fsg->bulk_in); + if (rc == -EAGAIN) + VDBG(fsg, "delayed bulk-in endpoint halt\n"); + while (rc != 0) { + if (rc != -EAGAIN) { + WARNING(fsg, "usb_ep_set_halt -> %d\n", rc); + rc = 0; + break; + } + + rc = usb_ep_set_halt(fsg->bulk_in); + } + return rc; +} + +static int wedge_bulk_in_endpoint(struct fsg_dev *fsg) +{ + int rc; + + DBG(fsg, "bulk-in set wedge\n"); + rc = 0; /* usb_ep_set_wedge(fsg->bulk_in); */ + if (rc == -EAGAIN) + VDBG(fsg, "delayed bulk-in endpoint wedge\n"); + while (rc != 0) { + if (rc != -EAGAIN) { + WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc); + rc = 0; + break; + } + } + return rc; +} + +static int pad_with_zeros(struct fsg_dev *fsg) +{ + struct fsg_buffhd *bh = fsg->common->next_buffhd_to_fill; + u32 nkeep = bh->inreq->length; + u32 nsend; + int rc; + + bh->state = BUF_STATE_EMPTY; /* For the first iteration */ + fsg->common->usb_amount_left = nkeep + fsg->common->residue; + while (fsg->common->usb_amount_left > 0) { + + /* Wait for the next buffer to be free */ + while (bh->state != BUF_STATE_EMPTY) { + rc = sleep_thread(fsg->common); + if (rc) + return rc; + } + + nsend = min(fsg->common->usb_amount_left, FSG_BUFLEN); + memset(bh->buf + nkeep, 0, nsend - nkeep); + bh->inreq->length = nsend; + bh->inreq->zero = 0; + start_transfer(fsg, fsg->bulk_in, bh->inreq, + &bh->inreq_busy, &bh->state); + bh = fsg->common->next_buffhd_to_fill = bh->next; + fsg->common->usb_amount_left -= nsend; + nkeep = 0; + } + return 0; +} + +static int throw_away_data(struct fsg_common *common) +{ + struct fsg_buffhd *bh; + u32 amount; + int rc; + + for (bh = common->next_buffhd_to_drain; + bh->state != BUF_STATE_EMPTY || common->usb_amount_left > 0; + bh = common->next_buffhd_to_drain) { + + /* Throw away the data in a filled buffer */ + if (bh->state == BUF_STATE_FULL) { + bh->state = BUF_STATE_EMPTY; + common->next_buffhd_to_drain = bh->next; + + /* A short packet or an error ends everything */ + if (bh->outreq->actual != bh->outreq->length || + bh->outreq->status != 0) { + raise_exception(common, + FSG_STATE_ABORT_BULK_OUT); + return -EINTR; + } + continue; + } + + /* Try to submit another request if we need one */ + bh = common->next_buffhd_to_fill; + if (bh->state == BUF_STATE_EMPTY + && common->usb_amount_left > 0) { + amount = min(common->usb_amount_left, FSG_BUFLEN); + + /* amount is always divisible by 512, hence by + * the bulk-out maxpacket size */ + bh->outreq->length = amount; + bh->bulk_out_intended_length = amount; + bh->outreq->short_not_ok = 1; + START_TRANSFER_OR(common, bulk_out, bh->outreq, + &bh->outreq_busy, &bh->state) + /* Don't know what to do if + * common->fsg is NULL */ + return -EIO; + common->next_buffhd_to_fill = bh->next; + common->usb_amount_left -= amount; + continue; + } + + /* Otherwise wait for something to happen */ + rc = sleep_thread(common); + if (rc) + return rc; + } + return 0; +} + + +static int finish_reply(struct fsg_common *common) +{ + struct fsg_buffhd *bh = common->next_buffhd_to_fill; + int rc = 0; + + switch (common->data_dir) { + case DATA_DIR_NONE: + break; /* Nothing to send */ + + /* If we don't know whether the host wants to read or write, + * this must be CB or CBI with an unknown command. We mustn't + * try to send or receive any data. So stall both bulk pipes + * if we can and wait for a reset. */ + case DATA_DIR_UNKNOWN: + if (!common->can_stall) { + /* Nothing */ + } else if (fsg_is_set(common)) { + fsg_set_halt(common->fsg, common->fsg->bulk_out); + rc = halt_bulk_in_endpoint(common->fsg); + } else { + /* Don't know what to do if common->fsg is NULL */ + rc = -EIO; + } + break; + + /* All but the last buffer of data must have already been sent */ + case DATA_DIR_TO_HOST: + if (common->data_size == 0) { + /* Nothing to send */ + + /* If there's no residue, simply send the last buffer */ + } else if (common->residue == 0) { + bh->inreq->zero = 0; + START_TRANSFER_OR(common, bulk_in, bh->inreq, + &bh->inreq_busy, &bh->state) + return -EIO; + common->next_buffhd_to_fill = bh->next; + + /* For Bulk-only, if we're allowed to stall then send the + * short packet and halt the bulk-in endpoint. If we can't + * stall, pad out the remaining data with 0's. */ + } else if (common->can_stall) { + bh->inreq->zero = 1; + START_TRANSFER_OR(common, bulk_in, bh->inreq, + &bh->inreq_busy, &bh->state) + /* Don't know what to do if + * common->fsg is NULL */ + rc = -EIO; + common->next_buffhd_to_fill = bh->next; + if (common->fsg) + rc = halt_bulk_in_endpoint(common->fsg); + } else if (fsg_is_set(common)) { + rc = pad_with_zeros(common->fsg); + } else { + /* Don't know what to do if common->fsg is NULL */ + rc = -EIO; + } + break; + + /* We have processed all we want from the data the host has sent. + * There may still be outstanding bulk-out requests. */ + case DATA_DIR_FROM_HOST: + if (common->residue == 0) { + /* Nothing to receive */ + + /* Did the host stop sending unexpectedly early? */ + } else if (common->short_packet_received) { + raise_exception(common, FSG_STATE_ABORT_BULK_OUT); + rc = -EINTR; + + /* We haven't processed all the incoming data. Even though + * we may be allowed to stall, doing so would cause a race. + * The controller may already have ACK'ed all the remaining + * bulk-out packets, in which case the host wouldn't see a + * STALL. Not realizing the endpoint was halted, it wouldn't + * clear the halt -- leading to problems later on. */ +#if 0 + } else if (common->can_stall) { + if (fsg_is_set(common)) + fsg_set_halt(common->fsg, + common->fsg->bulk_out); + raise_exception(common, FSG_STATE_ABORT_BULK_OUT); + rc = -EINTR; +#endif + + /* We can't stall. Read in the excess data and throw it + * all away. */ + } else { + rc = throw_away_data(common); + } + break; + } + return rc; +} + + +static int send_status(struct fsg_common *common) +{ + struct fsg_lun *curlun = &common->luns[common->lun]; + struct fsg_buffhd *bh; + struct bulk_cs_wrap *csw; + int rc; + u8 status = USB_STATUS_PASS; + u32 sd, sdinfo = 0; + + /* Wait for the next buffer to become available */ + bh = common->next_buffhd_to_fill; + while (bh->state != BUF_STATE_EMPTY) { + rc = sleep_thread(common); + if (rc) + return rc; + } + + if (curlun) + sd = curlun->sense_data; + else if (common->bad_lun_okay) + sd = SS_NO_SENSE; + else + sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; + + if (common->phase_error) { + DBG(common, "sending phase-error status\n"); + status = USB_STATUS_PHASE_ERROR; + sd = SS_INVALID_COMMAND; + } else if (sd != SS_NO_SENSE) { + DBG(common, "sending command-failure status\n"); + status = USB_STATUS_FAIL; + VDBG(common, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;" + " info x%x\n", + SK(sd), ASC(sd), ASCQ(sd), sdinfo); + } + + /* Store and send the Bulk-only CSW */ + csw = (void *)bh->buf; + + csw->Signature = cpu_to_le32(USB_BULK_CS_SIG); + csw->Tag = common->tag; + csw->Residue = cpu_to_le32(common->residue); + csw->Status = status; + + bh->inreq->length = USB_BULK_CS_WRAP_LEN; + bh->inreq->zero = 0; + START_TRANSFER_OR(common, bulk_in, bh->inreq, + &bh->inreq_busy, &bh->state) + /* Don't know what to do if common->fsg is NULL */ + return -EIO; + + common->next_buffhd_to_fill = bh->next; + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +/* Check whether the command is properly formed and whether its data size + * and direction agree with the values we already have. */ +static int check_command(struct fsg_common *common, int cmnd_size, + enum data_direction data_dir, unsigned int mask, + int needs_medium, const char *name) +{ + int i; + int lun = common->cmnd[1] >> 5; + static const char dirletter[4] = {'u', 'o', 'i', 'n'}; + char hdlen[20]; + struct fsg_lun *curlun; + + hdlen[0] = 0; + if (common->data_dir != DATA_DIR_UNKNOWN) + sprintf(hdlen, ", H%c=%u", dirletter[(int) common->data_dir], + common->data_size); + VDBG(common, "SCSI command: %s; Dc=%d, D%c=%u; Hc=%d%s\n", + name, cmnd_size, dirletter[(int) data_dir], + common->data_size_from_cmnd, common->cmnd_size, hdlen); + + /* We can't reply at all until we know the correct data direction + * and size. */ + if (common->data_size_from_cmnd == 0) + data_dir = DATA_DIR_NONE; + if (common->data_size < common->data_size_from_cmnd) { + /* Host data size < Device data size is a phase error. + * Carry out the command, but only transfer as much as + * we are allowed. */ + common->data_size_from_cmnd = common->data_size; + common->phase_error = 1; + } + common->residue = common->data_size; + common->usb_amount_left = common->data_size; + + /* Conflicting data directions is a phase error */ + if (common->data_dir != data_dir + && common->data_size_from_cmnd > 0) { + common->phase_error = 1; + return -EINVAL; + } + + /* Verify the length of the command itself */ + if (cmnd_size != common->cmnd_size) { + + /* Special case workaround: There are plenty of buggy SCSI + * implementations. Many have issues with cbw->Length + * field passing a wrong command size. For those cases we + * always try to work around the problem by using the length + * sent by the host side provided it is at least as large + * as the correct command length. + * Examples of such cases would be MS-Windows, which issues + * REQUEST SENSE with cbw->Length == 12 where it should + * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and + * REQUEST SENSE with cbw->Length == 10 where it should + * be 6 as well. + */ + if (cmnd_size <= common->cmnd_size) { + DBG(common, "%s is buggy! Expected length %d " + "but we got %d\n", name, + cmnd_size, common->cmnd_size); + cmnd_size = common->cmnd_size; + } else { + common->phase_error = 1; + return -EINVAL; + } + } + + /* Check that the LUN values are consistent */ + if (common->lun != lun) + DBG(common, "using LUN %d from CBW, not LUN %d from CDB\n", + common->lun, lun); + + /* Check the LUN */ + if (common->lun >= 0 && common->lun < common->nluns) { + curlun = &common->luns[common->lun]; + if (common->cmnd[0] != SC_REQUEST_SENSE) { + curlun->sense_data = SS_NO_SENSE; + curlun->info_valid = 0; + } + } else { + curlun = NULL; + common->bad_lun_okay = 0; + + /* INQUIRY and REQUEST SENSE commands are explicitly allowed + * to use unsupported LUNs; all others may not. */ + if (common->cmnd[0] != SC_INQUIRY && + common->cmnd[0] != SC_REQUEST_SENSE) { + DBG(common, "unsupported LUN %d\n", common->lun); + return -EINVAL; + } + } +#if 0 + /* If a unit attention condition exists, only INQUIRY and + * REQUEST SENSE commands are allowed; anything else must fail. */ + if (curlun && curlun->unit_attention_data != SS_NO_SENSE && + common->cmnd[0] != SC_INQUIRY && + common->cmnd[0] != SC_REQUEST_SENSE) { + curlun->sense_data = curlun->unit_attention_data; + curlun->unit_attention_data = SS_NO_SENSE; + return -EINVAL; + } +#endif + /* Check that only command bytes listed in the mask are non-zero */ + common->cmnd[1] &= 0x1f; /* Mask away the LUN */ + for (i = 1; i < cmnd_size; ++i) { + if (common->cmnd[i] && !(mask & (1 << i))) { + if (curlun) + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + } + + return 0; +} + + +static int do_scsi_command(struct fsg_common *common) +{ + struct fsg_buffhd *bh; + int rc; + int reply = -EINVAL; + int i; + static char unknown[16]; + struct fsg_lun *curlun = &common->luns[common->lun]; + + dump_cdb(common); + + /* Wait for the next buffer to become available for data or status */ + bh = common->next_buffhd_to_fill; + common->next_buffhd_to_drain = bh; + while (bh->state != BUF_STATE_EMPTY) { + rc = sleep_thread(common); + if (rc) + return rc; + } + common->phase_error = 0; + common->short_packet_received = 0; + + down_read(&common->filesem); /* We're using the backing file */ + switch (common->cmnd[0]) { + + case SC_INQUIRY: + common->data_size_from_cmnd = common->cmnd[4]; + reply = check_command(common, 6, DATA_DIR_TO_HOST, + (1<<4), 0, + "INQUIRY"); + if (reply == 0) + reply = do_inquiry(common, bh); + break; + + case SC_MODE_SELECT_6: + common->data_size_from_cmnd = common->cmnd[4]; + reply = check_command(common, 6, DATA_DIR_FROM_HOST, + (1<<1) | (1<<4), 0, + "MODE SELECT(6)"); + if (reply == 0) + reply = do_mode_select(common, bh); + break; + + case SC_MODE_SELECT_10: + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]); + reply = check_command(common, 10, DATA_DIR_FROM_HOST, + (1<<1) | (3<<7), 0, + "MODE SELECT(10)"); + if (reply == 0) + reply = do_mode_select(common, bh); + break; + + case SC_MODE_SENSE_6: + common->data_size_from_cmnd = common->cmnd[4]; + reply = check_command(common, 6, DATA_DIR_TO_HOST, + (1<<1) | (1<<2) | (1<<4), 0, + "MODE SENSE(6)"); + if (reply == 0) + reply = do_mode_sense(common, bh); + break; + + case SC_MODE_SENSE_10: + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]); + reply = check_command(common, 10, DATA_DIR_TO_HOST, + (1<<1) | (1<<2) | (3<<7), 0, + "MODE SENSE(10)"); + if (reply == 0) + reply = do_mode_sense(common, bh); + break; + + case SC_PREVENT_ALLOW_MEDIUM_REMOVAL: + common->data_size_from_cmnd = 0; + reply = check_command(common, 6, DATA_DIR_NONE, + (1<<4), 0, + "PREVENT-ALLOW MEDIUM REMOVAL"); + if (reply == 0) + reply = do_prevent_allow(common); + break; + + case SC_READ_6: + i = common->cmnd[4]; + common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; + reply = check_command(common, 6, DATA_DIR_TO_HOST, + (7<<1) | (1<<4), 1, + "READ(6)"); + if (reply == 0) + reply = do_read(common); + break; + + case SC_READ_10: + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]) << 9; + reply = check_command(common, 10, DATA_DIR_TO_HOST, + (1<<1) | (0xf<<2) | (3<<7), 1, + "READ(10)"); + if (reply == 0) + reply = do_read(common); + break; + + case SC_READ_12: + common->data_size_from_cmnd = + get_unaligned_be32(&common->cmnd[6]) << 9; + reply = check_command(common, 12, DATA_DIR_TO_HOST, + (1<<1) | (0xf<<2) | (0xf<<6), 1, + "READ(12)"); + if (reply == 0) + reply = do_read(common); + break; + + case SC_READ_CAPACITY: + common->data_size_from_cmnd = 8; + reply = check_command(common, 10, DATA_DIR_TO_HOST, + (0xf<<2) | (1<<8), 1, + "READ CAPACITY"); + if (reply == 0) + reply = do_read_capacity(common, bh); + break; + + case SC_READ_HEADER: + if (!common->luns[common->lun].cdrom) + goto unknown_cmnd; + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]); + reply = check_command(common, 10, DATA_DIR_TO_HOST, + (3<<7) | (0x1f<<1), 1, + "READ HEADER"); + if (reply == 0) + reply = do_read_header(common, bh); + break; + + case SC_READ_TOC: + if (!common->luns[common->lun].cdrom) + goto unknown_cmnd; + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]); + reply = check_command(common, 10, DATA_DIR_TO_HOST, + (7<<6) | (1<<1), 1, + "READ TOC"); + if (reply == 0) + reply = do_read_toc(common, bh); + break; + + case SC_READ_FORMAT_CAPACITIES: + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]); + reply = check_command(common, 10, DATA_DIR_TO_HOST, + (3<<7), 1, + "READ FORMAT CAPACITIES"); + if (reply == 0) + reply = do_read_format_capacities(common, bh); + break; + + case SC_REQUEST_SENSE: + common->data_size_from_cmnd = common->cmnd[4]; + reply = check_command(common, 6, DATA_DIR_TO_HOST, + (1<<4), 0, + "REQUEST SENSE"); + if (reply == 0) + reply = do_request_sense(common, bh); + break; + + case SC_START_STOP_UNIT: + common->data_size_from_cmnd = 0; + reply = check_command(common, 6, DATA_DIR_NONE, + (1<<1) | (1<<4), 0, + "START-STOP UNIT"); + if (reply == 0) + reply = do_start_stop(common); + break; + + case SC_SYNCHRONIZE_CACHE: + common->data_size_from_cmnd = 0; + reply = check_command(common, 10, DATA_DIR_NONE, + (0xf<<2) | (3<<7), 1, + "SYNCHRONIZE CACHE"); + if (reply == 0) + reply = do_synchronize_cache(common); + break; + + case SC_TEST_UNIT_READY: + common->data_size_from_cmnd = 0; + reply = check_command(common, 6, DATA_DIR_NONE, + 0, 1, + "TEST UNIT READY"); + break; + + /* Although optional, this command is used by MS-Windows. We + * support a minimal version: BytChk must be 0. */ + case SC_VERIFY: + common->data_size_from_cmnd = 0; + reply = check_command(common, 10, DATA_DIR_NONE, + (1<<1) | (0xf<<2) | (3<<7), 1, + "VERIFY"); + if (reply == 0) + reply = do_verify(common); + break; + + case SC_WRITE_6: + i = common->cmnd[4]; + common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; + reply = check_command(common, 6, DATA_DIR_FROM_HOST, + (7<<1) | (1<<4), 1, + "WRITE(6)"); + if (reply == 0) + reply = do_write(common); + break; + + case SC_WRITE_10: + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]) << 9; + reply = check_command(common, 10, DATA_DIR_FROM_HOST, + (1<<1) | (0xf<<2) | (3<<7), 1, + "WRITE(10)"); + if (reply == 0) + reply = do_write(common); + break; + + case SC_WRITE_12: + common->data_size_from_cmnd = + get_unaligned_be32(&common->cmnd[6]) << 9; + reply = check_command(common, 12, DATA_DIR_FROM_HOST, + (1<<1) | (0xf<<2) | (0xf<<6), 1, + "WRITE(12)"); + if (reply == 0) + reply = do_write(common); + break; + + /* Some mandatory commands that we recognize but don't implement. + * They don't mean much in this setting. It's left as an exercise + * for anyone interested to implement RESERVE and RELEASE in terms + * of Posix locks. */ + case SC_FORMAT_UNIT: + case SC_RELEASE: + case SC_RESERVE: + case SC_SEND_DIAGNOSTIC: + /* Fall through */ + + default: +unknown_cmnd: + common->data_size_from_cmnd = 0; + sprintf(unknown, "Unknown x%02x", common->cmnd[0]); + reply = check_command(common, common->cmnd_size, + DATA_DIR_UNKNOWN, 0xff, 0, unknown); + if (reply == 0) { + curlun->sense_data = SS_INVALID_COMMAND; + reply = -EINVAL; + } + break; + } + up_read(&common->filesem); + + if (reply == -EINTR) + return -EINTR; + + /* Set up the single reply buffer for finish_reply() */ + if (reply == -EINVAL) + reply = 0; /* Error reply length */ + if (reply >= 0 && common->data_dir == DATA_DIR_TO_HOST) { + reply = min((u32) reply, common->data_size_from_cmnd); + bh->inreq->length = reply; + bh->state = BUF_STATE_FULL; + common->residue -= reply; + } /* Otherwise it's already set */ + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) +{ + struct usb_request *req = bh->outreq; + struct fsg_bulk_cb_wrap *cbw = req->buf; + struct fsg_common *common = fsg->common; + + /* Was this a real packet? Should it be ignored? */ + if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) + return -EINVAL; + + /* Is the CBW valid? */ + if (req->actual != USB_BULK_CB_WRAP_LEN || + cbw->Signature != cpu_to_le32( + USB_BULK_CB_SIG)) { + DBG(fsg, "invalid CBW: len %u sig 0x%x\n", + req->actual, + le32_to_cpu(cbw->Signature)); + + /* The Bulk-only spec says we MUST stall the IN endpoint + * (6.6.1), so it's unavoidable. It also says we must + * retain this state until the next reset, but there's + * no way to tell the controller driver it should ignore + * Clear-Feature(HALT) requests. + * + * We aren't required to halt the OUT endpoint; instead + * we can simply accept and discard any data received + * until the next reset. */ + wedge_bulk_in_endpoint(fsg); + set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); + return -EINVAL; + } + + /* Is the CBW meaningful? */ + if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG || + cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) { + DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " + "cmdlen %u\n", + cbw->Lun, cbw->Flags, cbw->Length); + + /* We can do anything we want here, so let's stall the + * bulk pipes if we are allowed to. */ + if (common->can_stall) { + fsg_set_halt(fsg, fsg->bulk_out); + halt_bulk_in_endpoint(fsg); + } + return -EINVAL; + } + + /* Save the command for later */ + common->cmnd_size = cbw->Length; + memcpy(common->cmnd, cbw->CDB, common->cmnd_size); + if (cbw->Flags & USB_BULK_IN_FLAG) + common->data_dir = DATA_DIR_TO_HOST; + else + common->data_dir = DATA_DIR_FROM_HOST; + common->data_size = le32_to_cpu(cbw->DataTransferLength); + if (common->data_size == 0) + common->data_dir = DATA_DIR_NONE; + common->lun = cbw->Lun; + common->tag = cbw->Tag; + return 0; +} + + +static int get_next_command(struct fsg_common *common) +{ + struct fsg_buffhd *bh; + int rc = 0; + + /* Wait for the next buffer to become available */ + bh = common->next_buffhd_to_fill; + while (bh->state != BUF_STATE_EMPTY) { + rc = sleep_thread(common); + if (rc) + return rc; + } + + /* Queue a request to read a Bulk-only CBW */ + set_bulk_out_req_length(common, bh, USB_BULK_CB_WRAP_LEN); + bh->outreq->short_not_ok = 1; + START_TRANSFER_OR(common, bulk_out, bh->outreq, + &bh->outreq_busy, &bh->state) + /* Don't know what to do if common->fsg is NULL */ + return -EIO; + + /* We will drain the buffer in software, which means we + * can reuse it for the next filling. No need to advance + * next_buffhd_to_fill. */ + + /* Wait for the CBW to arrive */ + while (bh->state != BUF_STATE_FULL) { + rc = sleep_thread(common); + if (rc) + return rc; + } + + rc = fsg_is_set(common) ? received_cbw(common->fsg, bh) : -EIO; + bh->state = BUF_STATE_EMPTY; + + return rc; +} + + +/*-------------------------------------------------------------------------*/ + +static int enable_endpoint(struct fsg_common *common, struct usb_ep *ep, + const struct usb_endpoint_descriptor *d) +{ + int rc; + + ep->driver_data = common; + rc = usb_ep_enable(ep, d); + if (rc) + ERROR(common, "can't enable %s, result %d\n", ep->name, rc); + return rc; +} + +static int alloc_request(struct fsg_common *common, struct usb_ep *ep, + struct usb_request **preq) +{ + *preq = usb_ep_alloc_request(ep, GFP_ATOMIC); + if (*preq) + return 0; + ERROR(common, "can't allocate request for %s\n", ep->name); + return -ENOMEM; +} + +/* Reset interface setting and re-init endpoint state (toggle etc). */ +static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg) +{ + const struct usb_endpoint_descriptor *d; + struct fsg_dev *fsg; + int i, rc = 0; + + if (common->running) + DBG(common, "reset interface\n"); + +reset: + /* Deallocate the requests */ + if (common->fsg) { + fsg = common->fsg; + + for (i = 0; i < FSG_NUM_BUFFERS; ++i) { + struct fsg_buffhd *bh = &common->buffhds[i]; + + if (bh->inreq) { + usb_ep_free_request(fsg->bulk_in, bh->inreq); + bh->inreq = NULL; + } + if (bh->outreq) { + usb_ep_free_request(fsg->bulk_out, bh->outreq); + bh->outreq = NULL; + } + } + + /* Disable the endpoints */ + if (fsg->bulk_in_enabled) { + usb_ep_disable(fsg->bulk_in); + fsg->bulk_in_enabled = 0; + } + if (fsg->bulk_out_enabled) { + usb_ep_disable(fsg->bulk_out); + fsg->bulk_out_enabled = 0; + } + + common->fsg = NULL; + /* wake_up(&common->fsg_wait); */ + } + + common->running = 0; + if (!new_fsg || rc) + return rc; + + common->fsg = new_fsg; + fsg = common->fsg; + + /* Enable the endpoints */ + d = fsg_ep_desc(common->gadget, + &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc); + rc = enable_endpoint(common, fsg->bulk_in, d); + if (rc) + goto reset; + fsg->bulk_in_enabled = 1; + + d = fsg_ep_desc(common->gadget, + &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc); + rc = enable_endpoint(common, fsg->bulk_out, d); + if (rc) + goto reset; + fsg->bulk_out_enabled = 1; + common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize); + clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); + + /* Allocate the requests */ + for (i = 0; i < FSG_NUM_BUFFERS; ++i) { + struct fsg_buffhd *bh = &common->buffhds[i]; + + rc = alloc_request(common, fsg->bulk_in, &bh->inreq); + if (rc) + goto reset; + rc = alloc_request(common, fsg->bulk_out, &bh->outreq); + if (rc) + goto reset; + bh->inreq->buf = bh->outreq->buf = bh->buf; + bh->inreq->context = bh->outreq->context = bh; + bh->inreq->complete = bulk_in_complete; + bh->outreq->complete = bulk_out_complete; + } + + common->running = 1; + + return rc; +} + + +/****************************** ALT CONFIGS ******************************/ + + +static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) +{ + struct fsg_dev *fsg = fsg_from_func(f); + fsg->common->new_fsg = fsg; + raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); + return 0; +} + +static void fsg_disable(struct usb_function *f) +{ + struct fsg_dev *fsg = fsg_from_func(f); + fsg->common->new_fsg = NULL; + raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); +} + +/*-------------------------------------------------------------------------*/ + +static void handle_exception(struct fsg_common *common) +{ + int i; + struct fsg_buffhd *bh; + enum fsg_state old_state; + struct fsg_lun *curlun; + unsigned int exception_req_tag; + + /* Cancel all the pending transfers */ + if (common->fsg) { + for (i = 0; i < FSG_NUM_BUFFERS; ++i) { + bh = &common->buffhds[i]; + if (bh->inreq_busy) + usb_ep_dequeue(common->fsg->bulk_in, bh->inreq); + if (bh->outreq_busy) + usb_ep_dequeue(common->fsg->bulk_out, + bh->outreq); + } + + /* Wait until everything is idle */ + for (;;) { + int num_active = 0; + for (i = 0; i < FSG_NUM_BUFFERS; ++i) { + bh = &common->buffhds[i]; + num_active += bh->inreq_busy + bh->outreq_busy; + } + if (num_active == 0) + break; + if (sleep_thread(common)) + return; + } + + /* Clear out the controller's fifos */ + if (common->fsg->bulk_in_enabled) + usb_ep_fifo_flush(common->fsg->bulk_in); + if (common->fsg->bulk_out_enabled) + usb_ep_fifo_flush(common->fsg->bulk_out); + } + + /* Reset the I/O buffer states and pointers, the SCSI + * state, and the exception. Then invoke the handler. */ + + for (i = 0; i < FSG_NUM_BUFFERS; ++i) { + bh = &common->buffhds[i]; + bh->state = BUF_STATE_EMPTY; + } + common->next_buffhd_to_fill = &common->buffhds[0]; + common->next_buffhd_to_drain = &common->buffhds[0]; + exception_req_tag = common->exception_req_tag; + old_state = common->state; + + if (old_state == FSG_STATE_ABORT_BULK_OUT) + common->state = FSG_STATE_STATUS_PHASE; + else { + for (i = 0; i < common->nluns; ++i) { + curlun = &common->luns[i]; + curlun->sense_data = SS_NO_SENSE; + curlun->info_valid = 0; + } + common->state = FSG_STATE_IDLE; + } + + /* Carry out any extra actions required for the exception */ + switch (old_state) { + case FSG_STATE_ABORT_BULK_OUT: + send_status(common); + + if (common->state == FSG_STATE_STATUS_PHASE) + common->state = FSG_STATE_IDLE; + break; + + case FSG_STATE_RESET: + /* In case we were forced against our will to halt a + * bulk endpoint, clear the halt now. (The SuperH UDC + * requires this.) */ + if (!fsg_is_set(common)) + break; + if (test_and_clear_bit(IGNORE_BULK_OUT, + &common->fsg->atomic_bitflags)) + usb_ep_clear_halt(common->fsg->bulk_in); + + if (common->ep0_req_tag == exception_req_tag) + ep0_queue(common); /* Complete the status stage */ + + break; + + case FSG_STATE_CONFIG_CHANGE: + do_set_interface(common, common->new_fsg); + break; + + case FSG_STATE_EXIT: + case FSG_STATE_TERMINATED: + do_set_interface(common, NULL); /* Free resources */ + common->state = FSG_STATE_TERMINATED; /* Stop the thread */ + break; + + case FSG_STATE_INTERFACE_CHANGE: + case FSG_STATE_DISCONNECT: + case FSG_STATE_COMMAND_PHASE: + case FSG_STATE_DATA_PHASE: + case FSG_STATE_STATUS_PHASE: + case FSG_STATE_IDLE: + break; + } +} + +/*-------------------------------------------------------------------------*/ + +int fsg_main_thread(void *common_) +{ + struct fsg_common *common = the_fsg_common; + /* The main loop */ + do { + if (exception_in_progress(common)) { + handle_exception(common); + continue; + } + + if (!common->running) { + sleep_thread(common); + continue; + } + + if (get_next_command(common)) + continue; + + if (!exception_in_progress(common)) + common->state = FSG_STATE_DATA_PHASE; + + if (do_scsi_command(common) || finish_reply(common)) + continue; + + if (!exception_in_progress(common)) + common->state = FSG_STATE_STATUS_PHASE; + + if (send_status(common)) + continue; + + if (!exception_in_progress(common)) + common->state = FSG_STATE_IDLE; + } while (0); + + common->thread_task = NULL; + + return 0; +} + +static void fsg_common_release(struct kref *ref); + +static struct fsg_common *fsg_common_init(struct fsg_common *common, + struct usb_composite_dev *cdev) +{ + struct usb_gadget *gadget = cdev->gadget; + struct fsg_buffhd *bh; + struct fsg_lun *curlun; + int nluns, i, rc; + + /* Find out how many LUNs there should be */ + nluns = 1; + if (nluns < 1 || nluns > FSG_MAX_LUNS) { + printf("invalid number of LUNs: %u\n", nluns); + return ERR_PTR(-EINVAL); + } + + /* Allocate? */ + if (!common) { + common = calloc(sizeof *common, 1); + if (!common) + return ERR_PTR(-ENOMEM); + common->free_storage_on_release = 1; + } else { + memset(common, 0, sizeof common); + common->free_storage_on_release = 0; + } + + common->ops = NULL; + common->private_data = NULL; + + common->gadget = gadget; + common->ep0 = gadget->ep0; + common->ep0req = cdev->req; + + /* Maybe allocate device-global string IDs, and patch descriptors */ + if (fsg_strings[FSG_STRING_INTERFACE].id == 0) { + rc = usb_string_id(cdev); + if (unlikely(rc < 0)) + goto error_release; + fsg_strings[FSG_STRING_INTERFACE].id = rc; + fsg_intf_desc.iInterface = rc; + } + + /* Create the LUNs, open their backing files, and register the + * LUN devices in sysfs. */ + curlun = calloc(nluns, sizeof *curlun); + if (!curlun) { + rc = -ENOMEM; + goto error_release; + } + common->nluns = nluns; + + for (i = 0; i < nluns; i++) { + common->luns[i].removable = 1; + + rc = fsg_lun_open(&common->luns[i], ""); + if (rc) + goto error_luns; + } + common->lun = 0; + + /* Data buffers cyclic list */ + bh = common->buffhds; + + i = FSG_NUM_BUFFERS; + goto buffhds_first_it; + do { + bh->next = bh + 1; + ++bh; +buffhds_first_it: + bh->inreq_busy = 0; + bh->outreq_busy = 0; + bh->buf = kmalloc(FSG_BUFLEN, GFP_KERNEL); + if (unlikely(!bh->buf)) { + rc = -ENOMEM; + goto error_release; + } + } while (--i); + bh->next = common->buffhds; + + snprintf(common->inquiry_string, sizeof common->inquiry_string, + "%-8s%-16s%04x", + "Linux ", + "File-Store Gadget", + 0xffff); + + /* Some peripheral controllers are known not to be able to + * halt bulk endpoints correctly. If one of them is present, + * disable stalls. + */ + + /* Tell the thread to start working */ + common->thread_task = + kthread_create(fsg_main_thread, common, + OR(cfg->thread_name, "file-storage")); + if (IS_ERR(common->thread_task)) { + rc = PTR_ERR(common->thread_task); + goto error_release; + } + +#undef OR + /* Information */ + INFO(common, FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n"); + INFO(common, "Number of LUNs=%d\n", common->nluns); + + return common; + +error_luns: + common->nluns = i + 1; +error_release: + common->state = FSG_STATE_TERMINATED; /* The thread is dead */ + /* Call fsg_common_release() directly, ref might be not + * initialised */ + fsg_common_release(&common->ref); + return ERR_PTR(rc); +} + +static void fsg_common_release(struct kref *ref) +{ + struct fsg_common *common = container_of(ref, struct fsg_common, ref); + + /* If the thread isn't already dead, tell it to exit now */ + if (common->state != FSG_STATE_TERMINATED) { + raise_exception(common, FSG_STATE_EXIT); + wait_for_completion(&common->thread_notifier); + } + + if (likely(common->luns)) { + struct fsg_lun *lun = common->luns; + unsigned i = common->nluns; + + /* In error recovery common->nluns may be zero. */ + for (; i; --i, ++lun) + fsg_lun_close(lun); + + kfree(common->luns); + } + + { + struct fsg_buffhd *bh = common->buffhds; + unsigned i = FSG_NUM_BUFFERS; + do { + kfree(bh->buf); + } while (++bh, --i); + } + + if (common->free_storage_on_release) + kfree(common); +} + + +/*-------------------------------------------------------------------------*/ + +/** + * usb_copy_descriptors - copy a vector of USB descriptors + * @src: null-terminated vector to copy + * Context: initialization code, which may sleep + * + * This makes a copy of a vector of USB descriptors. Its primary use + * is to support usb_function objects which can have multiple copies, + * each needing different descriptors. Functions may have static + * tables of descriptors, which are used as templates and customized + * with identifiers (for interfaces, strings, endpoints, and more) + * as needed by a given function instance. + */ +struct usb_descriptor_header ** +usb_copy_descriptors(struct usb_descriptor_header **src) +{ + struct usb_descriptor_header **tmp; + unsigned bytes; + unsigned n_desc; + void *mem; + struct usb_descriptor_header **ret; + + /* count descriptors and their sizes; then add vector size */ + for (bytes = 0, n_desc = 0, tmp = src; *tmp; tmp++, n_desc++) + bytes += (*tmp)->bLength; + bytes += (n_desc + 1) * sizeof(*tmp); + + mem = kmalloc(bytes, GFP_KERNEL); + if (!mem) + return NULL; + + /* fill in pointers starting at "tmp", + * to descriptors copied starting at "mem"; + * and return "ret" + */ + tmp = mem; + ret = mem; + mem += (n_desc + 1) * sizeof(*tmp); + while (*src) { + memcpy(mem, *src, (*src)->bLength); + *tmp = mem; + tmp++; + mem += (*src)->bLength; + src++; + } + *tmp = NULL; + + return ret; +} + + + +static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) +{ + struct fsg_dev *fsg = fsg_from_func(f); + + DBG(fsg, "unbind\n"); + if (fsg->common->fsg == fsg) { + fsg->common->new_fsg = NULL; + raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); + } + + free(fsg->function.descriptors); + free(fsg->function.hs_descriptors); + kfree(fsg); +} + +static int fsg_bind(struct usb_configuration *c, struct usb_function *f) +{ + struct fsg_dev *fsg = fsg_from_func(f); + struct usb_gadget *gadget = c->cdev->gadget; + int i; + struct usb_ep *ep; + fsg->gadget = gadget; + + /* New interface */ + i = usb_interface_id(c, f); + if (i < 0) + return i; + fsg_intf_desc.bInterfaceNumber = i; + fsg->interface_number = i; + + /* Find all the endpoints we will use */ + ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc); + if (!ep) + goto autoconf_fail; + ep->driver_data = fsg->common; /* claim the endpoint */ + fsg->bulk_in = ep; + + ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc); + if (!ep) + goto autoconf_fail; + ep->driver_data = fsg->common; /* claim the endpoint */ + fsg->bulk_out = ep; + + /* Copy descriptors */ + f->descriptors = usb_copy_descriptors(fsg_fs_function); + if (unlikely(!f->descriptors)) + return -ENOMEM; + + if (gadget_is_dualspeed(gadget)) { + /* Assume endpoint addresses are the same for both speeds */ + fsg_hs_bulk_in_desc.bEndpointAddress = + fsg_fs_bulk_in_desc.bEndpointAddress; + fsg_hs_bulk_out_desc.bEndpointAddress = + fsg_fs_bulk_out_desc.bEndpointAddress; + f->hs_descriptors = usb_copy_descriptors(fsg_hs_function); + if (unlikely(!f->hs_descriptors)) { + free(f->descriptors); + return -ENOMEM; + } + } + return 0; + +autoconf_fail: + ERROR(fsg, "unable to autoconfigure all endpoints\n"); + return -ENOTSUPP; +} + + +/****************************** ADD FUNCTION ******************************/ + +static struct usb_gadget_strings *fsg_strings_array[] = { + &fsg_stringtab, + NULL, +}; + +static int fsg_bind_config(struct usb_composite_dev *cdev, + struct usb_configuration *c, + struct fsg_common *common) +{ + struct fsg_dev *fsg; + int rc; + + fsg = calloc(1, sizeof *fsg); + if (!fsg) + return -ENOMEM; + fsg->function.name = FSG_DRIVER_DESC; + fsg->function.strings = fsg_strings_array; + fsg->function.bind = fsg_bind; + fsg->function.unbind = fsg_unbind; + fsg->function.setup = fsg_setup; + fsg->function.set_alt = fsg_set_alt; + fsg->function.disable = fsg_disable; + + fsg->common = common; + common->fsg = fsg; + /* Our caller holds a reference to common structure so we + * don't have to be worry about it being freed until we return + * from this function. So instead of incrementing counter now + * and decrement in error recovery we increment it only when + * call to usb_add_function() was successful. */ + + rc = usb_add_function(c, &fsg->function); + + if (rc) + kfree(fsg); + + return rc; +} + +int fsg_add(struct usb_configuration *c) +{ + struct fsg_common *fsg_common; + + fsg_common = fsg_common_init(NULL, c->cdev); + + fsg_common->vendor_name = 0; + fsg_common->product_name = 0; + fsg_common->release = 0xffff; + + fsg_common->ops = NULL; + fsg_common->private_data = NULL; + + the_fsg_common = fsg_common; + + return fsg_bind_config(c->cdev, c, fsg_common); +} + +int fsg_init(struct ums_board_info *ums) +{ + ums_info = ums; + + return 0; +} diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c index a5a4c1f..cc3f344 100644 --- a/drivers/usb/gadget/g_dnl.c +++ b/drivers/usb/gadget/g_dnl.c @@ -31,6 +31,7 @@ #include "gadget_chips.h" #include "composite.c" +#include "f_mass_storage.c" /* * One needs to define the following: @@ -104,6 +105,8 @@ static int g_dnl_do_config(struct usb_configuration *c) printf("GADGET DRIVER: %s\n", s); if (!strcmp(s, "usb_dnl_dfu")) ret = dfu_add(c); + else if (!strcmp(s, "usb_dnl_ums")) + ret = fsg_add(c); return ret; } @@ -188,6 +191,9 @@ int g_dnl_register(const char *type) if (!strcmp(type, "dfu")) { strcpy(name, shortname); strcat(name, type); + } else if (!strcmp(type, "ums")) { + strcpy(name, shortname); + strcat(name, type); } else { printf("%s: unknown command: %s\n", __func__, type); return -EINVAL; diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c new file mode 100644 index 0000000..594dc10 --- /dev/null +++ b/drivers/usb/gadget/storage_common.c @@ -0,0 +1,653 @@ +/* + * storage_common.c -- Common definitions for mass storage functionality + * + * Copyright (C) 2003-2008 Alan Stern + * Copyeight (C) 2009 Samsung Electronics + * Author: Michal Nazarewicz (m.nazarewicz@samsung.com) + * + * Ported to u-boot: + * Andrzej Pietrasiewicz <andrzej.p@samsung.com> + * + * Code refactoring & cleanup: + * Łukasz Majewski <l.majewski@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* + * This file requires the following identifiers used in USB strings to + * be defined (each of type pointer to char): + * - fsg_string_manufacturer -- name of the manufacturer + * - fsg_string_product -- name of the product + * - fsg_string_serial -- product's serial + * - fsg_string_config -- name of the configuration + * - fsg_string_interface -- name of the interface + * The first four are only needed when FSG_DESCRIPTORS_DEVICE_STRINGS + * macro is defined prior to including this file. + */ + +/* + * When FSG_NO_INTR_EP is defined fsg_fs_intr_in_desc and + * fsg_hs_intr_in_desc objects as well as + * FSG_FS_FUNCTION_PRE_EP_ENTRIES and FSG_HS_FUNCTION_PRE_EP_ENTRIES + * macros are not defined. + * + * When FSG_NO_DEVICE_STRINGS is defined FSG_STRING_MANUFACTURER, + * FSG_STRING_PRODUCT, FSG_STRING_SERIAL and FSG_STRING_CONFIG are not + * defined (as well as corresponding entries in string tables are + * missing) and FSG_STRING_INTERFACE has value of zero. + * + * When FSG_NO_OTG is defined fsg_otg_desc won't be defined. + */ + +/* + * When FSG_BUFFHD_STATIC_BUFFER is defined when this file is included + * the fsg_buffhd structure's buf field will be an array of FSG_BUFLEN + * characters rather then a pointer to void. + */ + + +/* #include <asm/unaligned.h> */ + + +/* + * Thanks to NetChip Technologies for donating this product ID. + * + * DO NOT REUSE THESE IDs with any other driver!! Ever!! + * Instead: allocate your own, using normal USB-IF procedures. + */ +#define FSG_VENDOR_ID 0x0525 /* NetChip */ +#define FSG_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */ + +/*-------------------------------------------------------------------------*/ + +#ifndef DEBUG +#undef VERBOSE_DEBUG +#undef DUMP_MSGS +#endif /* !DEBUG */ + +#ifdef VERBOSE_DEBUG +#define VLDBG LDBG +#else +#define VLDBG(lun, fmt, args...) do { } while (0) +#endif /* VERBOSE_DEBUG */ + +/* +#define LDBG(lun, fmt, args...) dev_dbg (&(lun)->dev, fmt, ## args) +#define LERROR(lun, fmt, args...) dev_err (&(lun)->dev, fmt, ## args) +#define LWARN(lun, fmt, args...) dev_warn(&(lun)->dev, fmt, ## args) +#define LINFO(lun, fmt, args...) dev_info(&(lun)->dev, fmt, ## args) +*/ + +#define LDBG(lun, fmt, args...) do { } while (0) +#define LERROR(lun, fmt, args...) do { } while (0) +#define LWARN(lun, fmt, args...) do { } while (0) +#define LINFO(lun, fmt, args...) do { } while (0) + +/* + * Keep those macros in sync with those in + * include/linux/usb/composite.h or else GCC will complain. If they + * are identical (the same names of arguments, white spaces in the + * same places) GCC will allow redefinition otherwise (even if some + * white space is removed or added) warning will be issued. + * + * Those macros are needed here because File Storage Gadget does not + * include the composite.h header. For composite gadgets those macros + * are redundant since composite.h is included any way. + * + * One could check whether those macros are already defined (which + * would indicate composite.h had been included) or not (which would + * indicate we were in FSG) but this is not done because a warning is + * desired if definitions here differ from the ones in composite.h. + * + * We want the definitions to match and be the same in File Storage + * Gadget as well as Mass Storage Function (and so composite gadgets + * using MSF). If someone changes them in composite.h it will produce + * a warning in this file when building MSF. + */ + +#define DBG(d, fmt, args...) debug(fmt , ## args) +#define VDBG(d, fmt, args...) debug(fmt , ## args) +/* #define ERROR(d, fmt, args...) printf(fmt , ## args) */ +/* #define WARNING(d, fmt, args...) printf(fmt , ## args) */ +/* #define INFO(d, fmt, args...) printf(fmt , ## args) */ + +/* #define DBG(d, fmt, args...) do { } while (0) */ +/* #define VDBG(d, fmt, args...) do { } while (0) */ +#define ERROR(d, fmt, args...) do { } while (0) +#define WARNING(d, fmt, args...) do { } while (0) +#define INFO(d, fmt, args...) do { } while (0) + +#ifdef DUMP_MSGS + +/* dump_msg(fsg, const char * label, const u8 * buf, unsigned length); */ +# define dump_msg(fsg, label, buf, length) do { \ + if (length < 512) { \ + DBG(fsg, "%s, length %u:\n", label, length); \ + print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, \ + 16, 1, buf, length, 0); \ + } \ +} while (0) + +# define dump_cdb(fsg) do { } while (0) + +#else + +# define dump_msg(fsg, /* const char * */ label, \ + /* const u8 * */ buf, /* unsigned */ length) do { } while (0) + +# ifdef VERBOSE_DEBUG + +# define dump_cdb(fsg) \ + print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE, \ + 16, 1, (fsg)->cmnd, (fsg)->cmnd_size, 0) \ + +# else + +# define dump_cdb(fsg) do { } while (0) + +# endif /* VERBOSE_DEBUG */ + +#endif /* DUMP_MSGS */ + +/*-------------------------------------------------------------------------*/ + +/* SCSI device types */ +#define TYPE_DISK 0x00 +#define TYPE_CDROM 0x05 + +/* USB protocol value = the transport method */ +#define USB_PR_CBI 0x00 /* Control/Bulk/Interrupt */ +#define USB_PR_CB 0x01 /* Control/Bulk w/o interrupt */ +#define USB_PR_BULK 0x50 /* Bulk-only */ + +/* USB subclass value = the protocol encapsulation */ +#define USB_SC_RBC 0x01 /* Reduced Block Commands (flash) */ +#define USB_SC_8020 0x02 /* SFF-8020i, MMC-2, ATAPI (CD-ROM) */ +#define USB_SC_QIC 0x03 /* QIC-157 (tape) */ +#define USB_SC_UFI 0x04 /* UFI (floppy) */ +#define USB_SC_8070 0x05 /* SFF-8070i (removable) */ +#define USB_SC_SCSI 0x06 /* Transparent SCSI */ + +/* Bulk-only data structures */ + +/* Command Block Wrapper */ +struct fsg_bulk_cb_wrap { + __le32 Signature; /* Contains 'USBC' */ + u32 Tag; /* Unique per command id */ + __le32 DataTransferLength; /* Size of the data */ + u8 Flags; /* Direction in bit 7 */ + u8 Lun; /* LUN (normally 0) */ + u8 Length; /* Of the CDB, <= MAX_COMMAND_SIZE */ + u8 CDB[16]; /* Command Data Block */ +}; + +#define USB_BULK_CB_WRAP_LEN 31 +#define USB_BULK_CB_SIG 0x43425355 /* Spells out USBC */ +#define USB_BULK_IN_FLAG 0x80 + +/* Command Status Wrapper */ +struct bulk_cs_wrap { + __le32 Signature; /* Should = 'USBS' */ + u32 Tag; /* Same as original command */ + __le32 Residue; /* Amount not transferred */ + u8 Status; /* See below */ +}; + +#define USB_BULK_CS_WRAP_LEN 13 +#define USB_BULK_CS_SIG 0x53425355 /* Spells out 'USBS' */ +#define USB_STATUS_PASS 0 +#define USB_STATUS_FAIL 1 +#define USB_STATUS_PHASE_ERROR 2 + +/* Bulk-only class specific requests */ +#define USB_BULK_RESET_REQUEST 0xff +#define USB_BULK_GET_MAX_LUN_REQUEST 0xfe + +/* CBI Interrupt data structure */ +struct interrupt_data { + u8 bType; + u8 bValue; +}; + +#define CBI_INTERRUPT_DATA_LEN 2 + +/* CBI Accept Device-Specific Command request */ +#define USB_CBI_ADSC_REQUEST 0x00 + +/* Length of a SCSI Command Data Block */ +#define MAX_COMMAND_SIZE 16 + +/* SCSI commands that we recognize */ +#define SC_FORMAT_UNIT 0x04 +#define SC_INQUIRY 0x12 +#define SC_MODE_SELECT_6 0x15 +#define SC_MODE_SELECT_10 0x55 +#define SC_MODE_SENSE_6 0x1a +#define SC_MODE_SENSE_10 0x5a +#define SC_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e +#define SC_READ_6 0x08 +#define SC_READ_10 0x28 +#define SC_READ_12 0xa8 +#define SC_READ_CAPACITY 0x25 +#define SC_READ_FORMAT_CAPACITIES 0x23 +#define SC_READ_HEADER 0x44 +#define SC_READ_TOC 0x43 +#define SC_RELEASE 0x17 +#define SC_REQUEST_SENSE 0x03 +#define SC_RESERVE 0x16 +#define SC_SEND_DIAGNOSTIC 0x1d +#define SC_START_STOP_UNIT 0x1b +#define SC_SYNCHRONIZE_CACHE 0x35 +#define SC_TEST_UNIT_READY 0x00 +#define SC_VERIFY 0x2f +#define SC_WRITE_6 0x0a +#define SC_WRITE_10 0x2a +#define SC_WRITE_12 0xaa + +/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */ +#define SS_NO_SENSE 0 +#define SS_COMMUNICATION_FAILURE 0x040800 +#define SS_INVALID_COMMAND 0x052000 +#define SS_INVALID_FIELD_IN_CDB 0x052400 +#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x052100 +#define SS_LOGICAL_UNIT_NOT_SUPPORTED 0x052500 +#define SS_MEDIUM_NOT_PRESENT 0x023a00 +#define SS_MEDIUM_REMOVAL_PREVENTED 0x055302 +#define SS_NOT_READY_TO_READY_TRANSITION 0x062800 +#define SS_RESET_OCCURRED 0x062900 +#define SS_SAVING_PARAMETERS_NOT_SUPPORTED 0x053900 +#define SS_UNRECOVERED_READ_ERROR 0x031100 +#define SS_WRITE_ERROR 0x030c02 +#define SS_WRITE_PROTECTED 0x072700 + +#define SK(x) ((u8) ((x) >> 16)) /* Sense Key byte, etc. */ +#define ASC(x) ((u8) ((x) >> 8)) +#define ASCQ(x) ((u8) (x)) + +struct device_attribute { int i; }; +struct rw_semaphore { int i; }; +#define down_write(...) do { } while (0) +#define up_write(...) do { } while (0) +#define down_read(...) do { } while (0) +#define up_read(...) do { } while (0) +#define ETOOSMALL 525 + +#include <usb_mass_storage.h> +extern struct ums_board_info *ums_info; + +/*-------------------------------------------------------------------------*/ + +struct fsg_lun { + loff_t file_length; + loff_t num_sectors; + + unsigned int initially_ro:1; + unsigned int ro:1; + unsigned int removable:1; + unsigned int cdrom:1; + unsigned int prevent_medium_removal:1; + unsigned int registered:1; + unsigned int info_valid:1; + unsigned int nofua:1; + + u32 sense_data; + u32 sense_data_info; + u32 unit_attention_data; + + struct device dev; +}; + +#define fsg_lun_is_open(curlun) ((curlun)->filp != NULL) +#if 0 +static struct fsg_lun *fsg_lun_from_dev(struct device *dev) +{ + return container_of(dev, struct fsg_lun, dev); +} +#endif + +/* Big enough to hold our biggest descriptor */ +#define EP0_BUFSIZE 256 +#define DELAYED_STATUS (EP0_BUFSIZE + 999) /* An impossibly large value */ + +/* Number of buffers we will use. 2 is enough for double-buffering */ +#define FSG_NUM_BUFFERS 2 + +/* Default size of buffer length. */ +#define FSG_BUFLEN ((u32)16384) + +/* Maximal number of LUNs supported in mass storage function */ +#define FSG_MAX_LUNS 8 + +enum fsg_buffer_state { + BUF_STATE_EMPTY = 0, + BUF_STATE_FULL, + BUF_STATE_BUSY +}; + +struct fsg_buffhd { +#ifdef FSG_BUFFHD_STATIC_BUFFER + char buf[FSG_BUFLEN]; +#else + void *buf; +#endif + enum fsg_buffer_state state; + struct fsg_buffhd *next; + + /* + * The NetChip 2280 is faster, and handles some protocol faults + * better, if we don't submit any short bulk-out read requests. + * So we will record the intended request length here. + */ + unsigned int bulk_out_intended_length; + + struct usb_request *inreq; + int inreq_busy; + struct usb_request *outreq; + int outreq_busy; +}; + +enum fsg_state { + /* This one isn't used anywhere */ + FSG_STATE_COMMAND_PHASE = -10, + FSG_STATE_DATA_PHASE, + FSG_STATE_STATUS_PHASE, + + FSG_STATE_IDLE = 0, + FSG_STATE_ABORT_BULK_OUT, + FSG_STATE_RESET, + FSG_STATE_INTERFACE_CHANGE, + FSG_STATE_CONFIG_CHANGE, + FSG_STATE_DISCONNECT, + FSG_STATE_EXIT, + FSG_STATE_TERMINATED +}; + +enum data_direction { + DATA_DIR_UNKNOWN = 0, + DATA_DIR_FROM_HOST, + DATA_DIR_TO_HOST, + DATA_DIR_NONE +}; + +/*-------------------------------------------------------------------------*/ + +static inline u32 get_unaligned_be24(u8 *buf) +{ + return 0xffffff & (u32) get_unaligned_be32(buf - 1); +} + +/*-------------------------------------------------------------------------*/ + +enum { +#ifndef FSG_NO_DEVICE_STRINGS + FSG_STRING_MANUFACTURER = 1, + FSG_STRING_PRODUCT, + FSG_STRING_SERIAL, + FSG_STRING_CONFIG, +#endif + FSG_STRING_INTERFACE +}; + +#ifndef FSG_NO_OTG +static struct usb_otg_descriptor +fsg_otg_desc = { + .bLength = sizeof fsg_otg_desc, + .bDescriptorType = USB_DT_OTG, + + .bmAttributes = USB_OTG_SRP, +}; +#endif + +/* There is only one interface. */ + +static struct usb_interface_descriptor +fsg_intf_desc = { + .bLength = sizeof fsg_intf_desc, + .bDescriptorType = USB_DT_INTERFACE, + + .bNumEndpoints = 2, /* Adjusted during fsg_bind() */ + .bInterfaceClass = USB_CLASS_MASS_STORAGE, + .bInterfaceSubClass = USB_SC_SCSI, /* Adjusted during fsg_bind() */ + .bInterfaceProtocol = USB_PR_BULK, /* Adjusted during fsg_bind() */ + .iInterface = FSG_STRING_INTERFACE, +}; + +/* + * Three full-speed endpoint descriptors: bulk-in, bulk-out, and + * interrupt-in. + */ + +static struct usb_endpoint_descriptor +fsg_fs_bulk_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + /* wMaxPacketSize set by autoconfiguration */ +}; + +static struct usb_endpoint_descriptor +fsg_fs_bulk_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + /* wMaxPacketSize set by autoconfiguration */ +}; + +#ifndef FSG_NO_INTR_EP + +static struct usb_endpoint_descriptor +fsg_fs_intr_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = cpu_to_le16(2), + .bInterval = 32, /* frames -> 32 ms */ +}; + +#ifndef FSG_NO_OTG +# define FSG_FS_FUNCTION_PRE_EP_ENTRIES 2 +#else +# define FSG_FS_FUNCTION_PRE_EP_ENTRIES 1 +#endif + +#endif + +static struct usb_descriptor_header *fsg_fs_function[] = { +#ifndef FSG_NO_OTG + (struct usb_descriptor_header *) &fsg_otg_desc, +#endif + (struct usb_descriptor_header *) &fsg_intf_desc, + (struct usb_descriptor_header *) &fsg_fs_bulk_in_desc, + (struct usb_descriptor_header *) &fsg_fs_bulk_out_desc, +#ifndef FSG_NO_INTR_EP + (struct usb_descriptor_header *) &fsg_fs_intr_in_desc, +#endif + NULL, +}; + +/* + * USB 2.0 devices need to expose both high speed and full speed + * descriptors, unless they only run at full speed. + * + * That means alternate endpoint descriptors (bigger packets) + * and a "device qualifier" ... plus more construction options + * for the configuration descriptor. + */ +static struct usb_endpoint_descriptor +fsg_hs_bulk_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + /* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */ + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(512), +}; + +static struct usb_endpoint_descriptor +fsg_hs_bulk_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + /* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */ + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(512), + .bInterval = 1, /* NAK every 1 uframe */ +}; + +#ifndef FSG_NO_INTR_EP + +static struct usb_endpoint_descriptor +fsg_hs_intr_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + /* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */ + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = cpu_to_le16(2), + .bInterval = 9, /* 2**(9-1) = 256 uframes -> 32 ms */ +}; + +#ifndef FSG_NO_OTG +# define FSG_HS_FUNCTION_PRE_EP_ENTRIES 2 +#else +# define FSG_HS_FUNCTION_PRE_EP_ENTRIES 1 +#endif + +#endif + +static struct usb_descriptor_header *fsg_hs_function[] = { +#ifndef FSG_NO_OTG + (struct usb_descriptor_header *) &fsg_otg_desc, +#endif + (struct usb_descriptor_header *) &fsg_intf_desc, + (struct usb_descriptor_header *) &fsg_hs_bulk_in_desc, + (struct usb_descriptor_header *) &fsg_hs_bulk_out_desc, +#ifndef FSG_NO_INTR_EP + (struct usb_descriptor_header *) &fsg_hs_intr_in_desc, +#endif + NULL, +}; + +/* Maxpacket and other transfer characteristics vary by speed. */ +static struct usb_endpoint_descriptor * +fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs, + struct usb_endpoint_descriptor *hs) +{ + if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) + return hs; + return fs; +} + +/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */ +static struct usb_string fsg_strings[] = { +#ifndef FSG_NO_DEVICE_STRINGS + {FSG_STRING_MANUFACTURER, fsg_string_manufacturer}, + {FSG_STRING_PRODUCT, fsg_string_product}, + {FSG_STRING_SERIAL, fsg_string_serial}, + {FSG_STRING_CONFIG, fsg_string_config}, +#endif + {FSG_STRING_INTERFACE, fsg_string_interface}, + {} +}; + +static struct usb_gadget_strings fsg_stringtab = { + .language = 0x0409, /* en-us */ + .strings = fsg_strings, +}; + +/*-------------------------------------------------------------------------*/ + +/* + * If the next two routines are called while the gadget is registered, + * the caller must own fsg->filesem for writing. + */ + +static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) +{ + int ro; + int rc = -EINVAL; + loff_t size; + loff_t num_sectors; + loff_t min_sectors; + + /* R/W if we can, R/O if we must */ + ro = curlun->initially_ro; + + ums_info->get_capacity(&(ums_info->ums_dev), &size); + if (size < 0) { + printf("unable to find file size: %s\n", filename); + rc = (int) size; + goto out; + } + num_sectors = size >> 9; /* File size in 512-byte blocks */ + min_sectors = 1; + if (num_sectors < min_sectors) { + printf("file too small: %s\n", filename); + rc = -ETOOSMALL; + goto out; + } + + curlun->ro = ro; + curlun->file_length = size; + curlun->num_sectors = num_sectors; + debug("open backing file: %s\n", filename); + rc = 0; + +out: + return rc; +} + +static void fsg_lun_close(struct fsg_lun *curlun) +{ +} + +/*-------------------------------------------------------------------------*/ + +/* + * Sync the file data, don't bother with the metadata. + * This code was copied from fs/buffer.c:sys_fdatasync(). + */ +static int fsg_lun_fsync_sub(struct fsg_lun *curlun) +{ + return 0; +} + +static void store_cdrom_address(u8 *dest, int msf, u32 addr) +{ + if (msf) { + /* Convert to Minutes-Seconds-Frames */ + addr >>= 2; /* Convert to 2048-byte frames */ + addr += 2*75; /* Lead-in occupies 2 seconds */ + dest[3] = addr % 75; /* Frames */ + addr /= 75; + dest[2] = addr % 60; /* Seconds */ + addr /= 60; + dest[1] = addr; /* Minutes */ + dest[0] = 0; /* Reserved */ + } else { + /* Absolute sector */ + put_unaligned_be32(addr, dest); + } +} + +/*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 6c94794..87a5970 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -31,7 +31,6 @@ COBJS-$(CONFIG_USB_ATMEL) += ohci-at91.o COBJS-$(CONFIG_USB_OHCI_DA8XX) += ohci-da8xx.o COBJS-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o COBJS-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o -COBJS-$(CONFIG_USB_S3C64XX) += s3c64xx-hcd.o COBJS-$(CONFIG_USB_SL811HS) += sl811-hcd.o COBJS-$(CONFIG_USB_OHCI_S3C24XX) += ohci-s3c24xx.o @@ -54,6 +53,7 @@ COBJS-$(CONFIG_USB_EHCI_PPC4XX) += ehci-ppc4xx.o COBJS-$(CONFIG_USB_EHCI_IXP4XX) += ehci-ixp.o COBJS-$(CONFIG_USB_EHCI_MARVELL) += ehci-marvell.o COBJS-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o +COBJS-$(CONFIG_USB_EHCI_SPEAR) += ehci-spear.o COBJS-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o COBJS-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c index 3ca4c5c..0c797aa 100644 --- a/drivers/usb/host/ehci-exynos.c +++ b/drivers/usb/host/ehci-exynos.c @@ -42,11 +42,15 @@ DECLARE_GLOBAL_DATA_PTR; */ struct exynos_ehci { struct exynos_usb_phy *usb; - unsigned int *hcd; + struct ehci_hccr *hcd; }; +static struct exynos_ehci exynos; + +#ifdef CONFIG_OF_CONTROL static int exynos_usb_parse_dt(const void *blob, struct exynos_ehci *exynos) { + fdt_addr_t addr; unsigned int node; int depth; @@ -59,12 +63,14 @@ static int exynos_usb_parse_dt(const void *blob, struct exynos_ehci *exynos) /* * Get the base address for EHCI controller from the device node */ - exynos->hcd = (unsigned int *)fdtdec_get_addr(blob, node, "reg"); - if (exynos->hcd == NULL) { + addr = fdtdec_get_addr(blob, node, "reg"); + if (addr == FDT_ADDR_T_NONE) { debug("Can't get the EHCI register address\n"); return -ENXIO; } + exynos->hcd = (struct ehci_hccr *)addr; + depth = 0; node = fdtdec_next_compatible_subnode(blob, node, COMPAT_SAMSUNG_EXYNOS_USB_PHY, &depth); @@ -85,6 +91,7 @@ static int exynos_usb_parse_dt(const void *blob, struct exynos_ehci *exynos) return 0; } +#endif /* Setup the EHCI host controller. */ static void setup_usb_phy(struct exynos_usb_phy *usb) @@ -144,20 +151,21 @@ static void reset_usb_phy(struct exynos_usb_phy *usb) */ int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor) { - struct exynos_ehci *exynos = NULL; + struct exynos_ehci *ctx = &exynos; - exynos = (struct exynos_ehci *) - kzalloc(sizeof(struct exynos_ehci), GFP_KERNEL); - if (!exynos) { - debug("failed to allocate exynos ehci context\n"); - return -ENOMEM; +#ifdef CONFIG_OF_CONTROL + if (exynos_usb_parse_dt(gd->fdt_blob, ctx)) { + debug("Unable to parse device tree for ehci-exynos\n"); + return -ENODEV; } +#else + ctx->usb = (struct exynos_usb_phy *)samsung_get_base_usb_phy(); + ctx->hcd = (struct ehci_hccr *)samsung_get_base_usb_ehci(); +#endif - exynos_usb_parse_dt(gd->fdt_blob, exynos); + setup_usb_phy(ctx->usb); - setup_usb_phy(exynos->usb); - - *hccr = (struct ehci_hccr *)(exynos->hcd); + *hccr = ctx->hcd; *hcor = (struct ehci_hcor *)((uint32_t) *hccr + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); @@ -165,8 +173,6 @@ int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor) (uint32_t)*hccr, (uint32_t)*hcor, (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); - kfree(exynos); - return 0; } @@ -176,20 +182,9 @@ int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor) */ int ehci_hcd_stop(int index) { - struct exynos_ehci *exynos = NULL; - - exynos = (struct exynos_ehci *) - kzalloc(sizeof(struct exynos_ehci), GFP_KERNEL); - if (!exynos) { - debug("failed to allocate exynos ehci context\n"); - return -ENOMEM; - } - - exynos_usb_parse_dt(gd->fdt_blob, exynos); - - reset_usb_phy(exynos->usb); + struct exynos_ehci *ctx = &exynos; - kfree(exynos); + reset_usb_phy(ctx->usb); return 0; } diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 7f98a63..c816878 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -21,12 +21,14 @@ * MA 02111-1307 USA */ #include <common.h> +#include <errno.h> #include <asm/byteorder.h> #include <asm/unaligned.h> #include <usb.h> #include <asm/io.h> #include <malloc.h> #include <watchdog.h> +#include <linux/compiler.h> #include "ehci.h" @@ -39,7 +41,10 @@ static struct ehci_ctrl { struct ehci_hcor *hcor; int rootdev; uint16_t portreset; - struct QH qh_list __attribute__((aligned(USB_DMA_MINALIGN))); + struct QH qh_list __aligned(USB_DMA_MINALIGN); + struct QH periodic_queue __aligned(USB_DMA_MINALIGN); + uint32_t *periodic_list; + int ntds; } ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT]; #define ALIGN_END_ADDR(type, ptr, size) \ @@ -858,6 +863,8 @@ int usb_lowlevel_init(int index, void **controller) uint32_t reg; uint32_t cmd; struct QH *qh_list; + struct QH *periodic; + int i; if (ehci_hcd_init(index, &ehcic[index].hccr, &ehcic[index].hcor)) return -1; @@ -870,6 +877,9 @@ int usb_lowlevel_init(int index, void **controller) if (ehci_hcd_init(index, &ehcic[index].hccr, &ehcic[index].hcor)) return -1; #endif + /* Set the high address word (aka segment) for 64-bit controller */ + if (ehci_readl(&ehcic[index].hccr->cr_hccparams) & 1) + ehci_writel(ehcic[index].hcor->or_ctrldssegment, 0); qh_list = &ehcic[index].qh_list; @@ -884,6 +894,40 @@ int usb_lowlevel_init(int index, void **controller) qh_list->qh_overlay.qt_token = cpu_to_hc32(QT_TOKEN_STATUS(QT_TOKEN_STATUS_HALTED)); + /* Set async. queue head pointer. */ + ehci_writel(&ehcic[index].hcor->or_asynclistaddr, (uint32_t)qh_list); + + /* + * Set up periodic list + * Step 1: Parent QH for all periodic transfers. + */ + periodic = &ehcic[index].periodic_queue; + memset(periodic, 0, sizeof(*periodic)); + periodic->qh_link = cpu_to_hc32(QH_LINK_TERMINATE); + periodic->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); + periodic->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); + + /* + * Step 2: Setup frame-list: Every microframe, USB tries the same list. + * In particular, device specifications on polling frequency + * are disregarded. Keyboards seem to send NAK/NYet reliably + * when polled with an empty buffer. + * + * Split Transactions will be spread across microframes using + * S-mask and C-mask. + */ + ehcic[index].periodic_list = memalign(4096, 1024*4); + if (!ehcic[index].periodic_list) + return -ENOMEM; + for (i = 0; i < 1024; i++) { + ehcic[index].periodic_list[i] = (uint32_t)periodic + | QH_LINK_TYPE_QH; + } + + /* Set periodic list base address */ + ehci_writel(&ehcic[index].hcor->or_periodiclistbase, + (uint32_t)ehcic[index].periodic_list); + reg = ehci_readl(&ehcic[index].hccr->cr_hcsparams); descriptor.hub.bNbrPorts = HCS_N_PORTS(reg); debug("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts); @@ -953,10 +997,254 @@ submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, return ehci_submit_async(dev, pipe, buffer, length, setup); } +struct int_queue { + struct QH *first; + struct QH *current; + struct QH *last; + struct qTD *tds; +}; + +#define NEXT_QH(qh) (struct QH *)((qh)->qh_link & ~0x1f) + +static int +enable_periodic(struct ehci_ctrl *ctrl) +{ + uint32_t cmd; + struct ehci_hcor *hcor = ctrl->hcor; + int ret; + + cmd = ehci_readl(&hcor->or_usbcmd); + cmd |= CMD_PSE; + ehci_writel(&hcor->or_usbcmd, cmd); + + ret = handshake((uint32_t *)&hcor->or_usbsts, + STS_PSS, STS_PSS, 100 * 1000); + if (ret < 0) { + printf("EHCI failed: timeout when enabling periodic list\n"); + return -ETIMEDOUT; + } + udelay(1000); + return 0; +} + +static int +disable_periodic(struct ehci_ctrl *ctrl) +{ + uint32_t cmd; + struct ehci_hcor *hcor = ctrl->hcor; + int ret; + + cmd = ehci_readl(&hcor->or_usbcmd); + cmd &= ~CMD_PSE; + ehci_writel(&hcor->or_usbcmd, cmd); + + ret = handshake((uint32_t *)&hcor->or_usbsts, + STS_PSS, 0, 100 * 1000); + if (ret < 0) { + printf("EHCI failed: timeout when disabling periodic list\n"); + return -ETIMEDOUT; + } + return 0; +} + +static int periodic_schedules; + +struct int_queue * +create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize, + int elementsize, void *buffer) +{ + struct ehci_ctrl *ctrl = dev->controller; + struct int_queue *result = NULL; + int i; + + debug("Enter create_int_queue\n"); + if (usb_pipetype(pipe) != PIPE_INTERRUPT) { + debug("non-interrupt pipe (type=%lu)", usb_pipetype(pipe)); + return NULL; + } + + /* limit to 4 full pages worth of data - + * we can safely fit them in a single TD, + * no matter the alignment + */ + if (elementsize >= 16384) { + debug("too large elements for interrupt transfers\n"); + return NULL; + } + + result = malloc(sizeof(*result)); + if (!result) { + debug("ehci intr queue: out of memory\n"); + goto fail1; + } + result->first = memalign(32, sizeof(struct QH) * queuesize); + if (!result->first) { + debug("ehci intr queue: out of memory\n"); + goto fail2; + } + result->current = result->first; + result->last = result->first + queuesize - 1; + result->tds = memalign(32, sizeof(struct qTD) * queuesize); + if (!result->tds) { + debug("ehci intr queue: out of memory\n"); + goto fail3; + } + memset(result->first, 0, sizeof(struct QH) * queuesize); + memset(result->tds, 0, sizeof(struct qTD) * queuesize); + + for (i = 0; i < queuesize; i++) { + struct QH *qh = result->first + i; + struct qTD *td = result->tds + i; + void **buf = &qh->buffer; + + qh->qh_link = (uint32_t)(qh+1) | QH_LINK_TYPE_QH; + if (i == queuesize - 1) + qh->qh_link = QH_LINK_TERMINATE; + + qh->qh_overlay.qt_next = (uint32_t)td; + qh->qh_endpt1 = (0 << 28) | /* No NAK reload (ehci 4.9) */ + (usb_maxpacket(dev, pipe) << 16) | /* MPS */ + (1 << 14) | + QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)) | + (usb_pipeendpoint(pipe) << 8) | /* Endpoint Number */ + (usb_pipedevice(pipe) << 0); + qh->qh_endpt2 = (1 << 30) | /* 1 Tx per mframe */ + (1 << 0); /* S-mask: microframe 0 */ + if (dev->speed == USB_SPEED_LOW || + dev->speed == USB_SPEED_FULL) { + debug("TT: port: %d, hub address: %d\n", + dev->portnr, dev->parent->devnum); + qh->qh_endpt2 |= (dev->portnr << 23) | + (dev->parent->devnum << 16) | + (0x1c << 8); /* C-mask: microframes 2-4 */ + } + + td->qt_next = QT_NEXT_TERMINATE; + td->qt_altnext = QT_NEXT_TERMINATE; + debug("communication direction is '%s'\n", + usb_pipein(pipe) ? "in" : "out"); + td->qt_token = (elementsize << 16) | + ((usb_pipein(pipe) ? 1 : 0) << 8) | /* IN/OUT token */ + 0x80; /* active */ + td->qt_buffer[0] = (uint32_t)buffer + i * elementsize; + td->qt_buffer[1] = (td->qt_buffer[0] + 0x1000) & ~0xfff; + td->qt_buffer[2] = (td->qt_buffer[0] + 0x2000) & ~0xfff; + td->qt_buffer[3] = (td->qt_buffer[0] + 0x3000) & ~0xfff; + td->qt_buffer[4] = (td->qt_buffer[0] + 0x4000) & ~0xfff; + + *buf = buffer + i * elementsize; + } + + if (disable_periodic(ctrl) < 0) { + debug("FATAL: periodic should never fail, but did"); + goto fail3; + } + + /* hook up to periodic list */ + struct QH *list = &ctrl->periodic_queue; + result->last->qh_link = list->qh_link; + list->qh_link = (uint32_t)result->first | QH_LINK_TYPE_QH; + + if (enable_periodic(ctrl) < 0) { + debug("FATAL: periodic should never fail, but did"); + goto fail3; + } + periodic_schedules++; + + debug("Exit create_int_queue\n"); + return result; +fail3: + if (result->tds) + free(result->tds); +fail2: + if (result->first) + free(result->first); + if (result) + free(result); +fail1: + return NULL; +} + +void *poll_int_queue(struct usb_device *dev, struct int_queue *queue) +{ + struct QH *cur = queue->current; + + /* depleted queue */ + if (cur == NULL) { + debug("Exit poll_int_queue with completed queue\n"); + return NULL; + } + /* still active */ + if (cur->qh_overlay.qt_token & 0x80) { + debug("Exit poll_int_queue with no completed intr transfer. " + "token is %x\n", cur->qh_overlay.qt_token); + return NULL; + } + if (!(cur->qh_link & QH_LINK_TERMINATE)) + queue->current++; + else + queue->current = NULL; + debug("Exit poll_int_queue with completed intr transfer. " + "token is %x at %p (first at %p)\n", cur->qh_overlay.qt_token, + &cur->qh_overlay.qt_token, queue->first); + return cur->buffer; +} + +/* Do not free buffers associated with QHs, they're owned by someone else */ +int +destroy_int_queue(struct usb_device *dev, struct int_queue *queue) +{ + struct ehci_ctrl *ctrl = dev->controller; + int result = -1; + unsigned long timeout; + + if (disable_periodic(ctrl) < 0) { + debug("FATAL: periodic should never fail, but did"); + goto out; + } + periodic_schedules--; + + struct QH *cur = &ctrl->periodic_queue; + timeout = get_timer(0) + 500; /* abort after 500ms */ + while (!(cur->qh_link & QH_LINK_TERMINATE)) { + debug("considering %p, with qh_link %x\n", cur, cur->qh_link); + if (NEXT_QH(cur) == queue->first) { + debug("found candidate. removing from chain\n"); + cur->qh_link = queue->last->qh_link; + result = 0; + break; + } + cur = NEXT_QH(cur); + if (get_timer(0) > timeout) { + printf("Timeout destroying interrupt endpoint queue\n"); + result = -1; + goto out; + } + } + + if (periodic_schedules > 0) { + result = enable_periodic(ctrl); + if (result < 0) + debug("FATAL: periodic should never fail, but did"); + } + +out: + free(queue->tds); + free(queue->first); + free(queue); + + return result; +} + int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int length, int interval) { + void *backbuffer; + struct int_queue *queue; + unsigned long timeout; + int result = 0, ret; + debug("dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d", dev, pipe, buffer, length, interval); @@ -972,9 +1260,31 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, * not require more than a single qTD. */ if (length > usb_maxpacket(dev, pipe)) { - printf("%s: Interrupt transfers requiring several transactions " - "are not supported.\n", __func__); + printf("%s: Interrupt transfers requiring several " + "transactions are not supported.\n", __func__); return -1; } - return ehci_submit_async(dev, pipe, buffer, length, NULL); + + queue = create_int_queue(dev, pipe, 1, length, buffer); + + timeout = get_timer(0) + USB_TIMEOUT_MS(pipe); + while ((backbuffer = poll_int_queue(dev, queue)) == NULL) + if (get_timer(0) > timeout) { + printf("Timeout poll on interrupt endpoint\n"); + result = -ETIMEDOUT; + break; + } + + if (backbuffer != buffer) { + debug("got wrong buffer back (%x instead of %x)\n", + (uint32_t)backbuffer, (uint32_t)buffer); + return -EINVAL; + } + + ret = destroy_int_queue(dev, queue); + if (ret < 0) + return ret; + + /* everything worked out fine */ + return result; } diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 29af02d..90d7a6f 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -19,6 +19,7 @@ */ #include <common.h> +#include <errno.h> #include <pci.h> #include <usb.h> @@ -32,31 +33,76 @@ static struct pci_device_id ehci_pci_ids[] = { {0x12D8, 0x400F}, /* Pericom */ {0, 0} }; +#else +static pci_dev_t ehci_find_class(int index) +{ + int bus; + int devnum; + pci_dev_t bdf; + uint32_t class; + + for (bus = 0; bus <= pci_last_busno(); bus++) { + for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES-1; devnum++) { + pci_read_config_dword(PCI_BDF(bus, devnum, 0), + PCI_CLASS_REVISION, &class); + if (class >> 16 == 0xffff) + continue; + + for (bdf = PCI_BDF(bus, devnum, 0); + bdf <= PCI_BDF(bus, devnum, + PCI_MAX_PCI_FUNCTIONS - 1); + bdf += PCI_BDF(0, 0, 1)) { + pci_read_config_dword(bdf, PCI_CLASS_REVISION, + &class); + if ((class >> 8 == PCI_CLASS_SERIAL_USB_EHCI) + && !index--) + return bdf; + } + } + } + + return -ENODEV; +} #endif /* * Create the appropriate control structures to manage * a new EHCI host controller. */ -int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor) +int ehci_hcd_init(int index, struct ehci_hccr **ret_hccr, + struct ehci_hcor **ret_hcor) { pci_dev_t pdev; + uint32_t cmd; + struct ehci_hccr *hccr; + struct ehci_hcor *hcor; +#ifdef CONFIG_PCI_EHCI_DEVICE pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVICE); - if (pdev == -1) { +#else + pdev = ehci_find_class(index); +#endif + if (pdev < 0) { printf("EHCI host controller not found\n"); return -1; } - *hccr = (struct ehci_hccr *)pci_map_bar(pdev, + hccr = (struct ehci_hccr *)pci_map_bar(pdev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); - *hcor = (struct ehci_hcor *)((uint32_t) *hccr + - HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); + hcor = (struct ehci_hcor *)((uint32_t) hccr + + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); debug("EHCI-PCI init hccr 0x%x and hcor 0x%x hc_length %d\n", - (uint32_t)*hccr, (uint32_t)*hcor, - (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); + (uint32_t)hccr, (uint32_t)hcor, + (uint32_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase))); + + *ret_hccr = hccr; + *ret_hcor = hcor; + /* enable busmaster */ + pci_read_config_dword(pdev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER; + pci_write_config_dword(pdev, PCI_COMMAND, cmd); return 0; } diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c new file mode 100644 index 0000000..f99bd1f --- /dev/null +++ b/drivers/usb/host/ehci-spear.c @@ -0,0 +1,59 @@ +/* + * (C) Copyright 2010 + * Armando Visconti, ST Micoelectronics, <armando.visconti@st.com>. + * + * (C) Copyright 2009 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar <prafulla@marvell.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <usb.h> +#include "ehci.h" +#include <asm/arch/hardware.h> + + +/* + * Create the appropriate control structures to manage + * a new EHCI host controller. + */ +int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor) +{ + *hccr = (struct ehci_hccr *)(CONFIG_SYS_UHC0_EHCI_BASE + 0x100); + *hcor = (struct ehci_hcor *)((uint32_t)*hccr + + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); + + debug("SPEAr-ehci: init hccr %x and hcor %x hc_length %d\n", + (uint32_t)*hccr, (uint32_t)*hcor, + (uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); + + return 0; +} + +/* + * Destroy the appropriate control structures corresponding + * the the EHCI host controller. + */ +int ehci_hcd_stop(int index) +{ + return 0; +} diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 1e3cd79..d090f0a 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -69,6 +69,7 @@ struct ehci_hcor { #define CMD_RUN (1 << 0) /* start/stop HC */ uint32_t or_usbsts; #define STS_ASS (1 << 15) +#define STS_PSS (1 << 14) #define STS_HALT (1 << 12) uint32_t or_usbintr; #define INTR_UE (1 << 0) /* USB interrupt enable */ @@ -245,7 +246,10 @@ struct QH { * Add dummy fill value to make the size of this struct * aligned to 32 bytes */ - uint8_t fill[16]; + union { + uint32_t fill[4]; + void *buffer; + }; }; /* Low level init functions */ diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index bdbe250..bc17b85 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -66,7 +66,6 @@ #if defined(CONFIG_ARM920T) || \ defined(CONFIG_S3C24X0) || \ - defined(CONFIG_S3C6400) || \ defined(CONFIG_440EP) || \ defined(CONFIG_PCI_OHCI) || \ defined(CONFIG_MPC5200) || \ diff --git a/drivers/usb/musb-new/linux-compat.h b/drivers/usb/musb-new/linux-compat.h index 5c126ef..72c8c2b 100644 --- a/drivers/usb/musb-new/linux-compat.h +++ b/drivers/usb/musb-new/linux-compat.h @@ -12,8 +12,6 @@ #define __iomem #define __deprecated -typedef enum { false = 0, true = 1 } bool; - struct unused {}; typedef struct unused unused_t; diff --git a/drivers/usb/musb-new/musb_core.c b/drivers/usb/musb-new/musb_core.c index 040a5c0..da93571 100644 --- a/drivers/usb/musb-new/musb_core.c +++ b/drivers/usb/musb-new/musb_core.c @@ -943,7 +943,9 @@ void musb_start(struct musb *musb) /* put into basic highspeed mode and start session */ musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE +#ifdef CONFIG_USB_GADGET_DUALSPEED | MUSB_POWER_HSENAB +#endif /* ENSUSPEND wedges tusb */ /* | MUSB_POWER_ENSUSPEND */ ); @@ -1421,6 +1423,7 @@ static int __devinit musb_core_init(u16 musb_type, struct musb *musb) strcat(aInfo, ", dyn FIFOs"); musb->dyn_fifo = true; } +#ifndef CONFIG_MUSB_DISABLE_BULK_COMBINE_SPLIT if (reg & MUSB_CONFIGDATA_MPRXE) { strcat(aInfo, ", bulk combine"); musb->bulk_combine = true; @@ -1429,6 +1432,10 @@ static int __devinit musb_core_init(u16 musb_type, struct musb *musb) strcat(aInfo, ", bulk split"); musb->bulk_split = true; } +#else + musb->bulk_combine = false; + musb->bulk_split = false; +#endif if (reg & MUSB_CONFIGDATA_HBRXE) { strcat(aInfo, ", HB-ISO Rx"); musb->hb_iso_rx = true; diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c index 762cbc1..15d2ec0 100644 --- a/drivers/usb/musb-new/musb_uboot.c +++ b/drivers/usb/musb-new/musb_uboot.c @@ -174,7 +174,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) { int ret; - if (!driver || driver->speed < USB_SPEED_HIGH || !driver->bind || + if (!driver || driver->speed < USB_SPEED_FULL || !driver->bind || !driver->setup) { printf("bad parameter.\n"); return -EINVAL; diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 170a358..53952ab 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -35,11 +35,13 @@ COBJS-$(CONFIG_EXYNOS_MIPI_DSIM) += exynos_mipi_dsi.o exynos_mipi_dsi_common.o \ exynos_mipi_dsi_lowlevel.o COBJS-$(CONFIG_EXYNOS_PWM_BL) += exynos_pwm_bl.o COBJS-$(CONFIG_FSL_DIU_FB) += fsl_diu_fb.o videomodes.o +COBJS-$(CONFIG_MPC8XX_LCD) += mpc8xx_lcd.o +COBJS-$(CONFIG_PXA_LCD) += pxa_lcd.o COBJS-$(CONFIG_S6E8AX0) += s6e8ax0.o COBJS-$(CONFIG_S6E63D6) += s6e63d6.o COBJS-$(CONFIG_LD9040) += ld9040.o COBJS-$(CONFIG_SED156X) += sed156x.o -COBJS-$(CONFIG_VIDEO_AMBA) += amba.o +COBJS-$(CONFIG_VIDEO_BCM2835) += bcm2835.o COBJS-$(CONFIG_VIDEO_COREBOOT) += coreboot_fb.o COBJS-$(CONFIG_VIDEO_CT69000) += ct69000.o videomodes.o COBJS-$(CONFIG_VIDEO_DA8XX) += da8xx-fb.o videomodes.o diff --git a/drivers/video/amba.c b/drivers/video/amba.c deleted file mode 100644 index ffa1c39..0000000 --- a/drivers/video/amba.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Driver for AMBA PrimeCell CLCD - * - * Copyright (C) 2009 Alessandro Rubini - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <asm/io.h> -#include <lcd.h> -#include <amba_clcd.h> - -/* These variables are required by lcd.c -- although it sets them by itself */ -int lcd_line_length; -int lcd_color_fg; -int lcd_color_bg; -void *lcd_base; -void *lcd_console_address; -short console_col; -short console_row; - -/* - * To use this driver you need to provide the following in board files: - * a panel_info definition - * an lcd_enable function (can't define a weak default with current code) - */ - -/* There is nothing to do with color registers, we use true color */ -void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue) -{ - return; -} - -/* Low level initialization of the logic cell: depends on panel_info */ -void lcd_ctrl_init(void *lcdbase) -{ - struct clcd_config *config; - struct clcd_registers *regs; - u32 cntl; - - config = panel_info.priv; - regs = config->address; - cntl = config->cntl & ~CNTL_LCDEN; - - /* Lazily, just copy the registers over: first control with disable */ - writel(cntl, ®s->cntl); - - writel(config->tim0, ®s->tim0); - writel(config->tim1, ®s->tim1); - writel(config->tim2, ®s->tim2); - writel(config->tim3, ®s->tim3); - writel((u32)lcdbase, ®s->ubas); - /* finally, enable */ - writel(cntl | CNTL_LCDEN, ®s->cntl); -} - -/* This is trivial, and copied from atmel_lcdfb.c */ -ulong calc_fbsize(void) -{ - return ((panel_info.vl_col * panel_info.vl_row * - NBITS(panel_info.vl_bpix)) / 8) + PAGE_SIZE; -} diff --git a/drivers/video/atmel_hlcdfb.c b/drivers/video/atmel_hlcdfb.c index b10ca4b..fc95897 100644 --- a/drivers/video/atmel_hlcdfb.c +++ b/drivers/video/atmel_hlcdfb.c @@ -29,16 +29,6 @@ #include <lcd.h> #include <atmel_hlcdc.h> -int lcd_line_length; -int lcd_color_fg; -int lcd_color_bg; - -void *lcd_base; /* Start of framebuffer memory */ -void *lcd_console_address; /* Start of console buffer */ - -short console_col; -short console_row; - /* configurable parameters */ #define ATMEL_LCDC_CVAL_DEFAULT 0xc8 #define ATMEL_LCDC_DMA_BURST_LEN 8 diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index c02ffd8..2afeab2 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -29,16 +29,6 @@ #include <lcd.h> #include <atmel_lcdc.h> -int lcd_line_length; -int lcd_color_fg; -int lcd_color_bg; - -void *lcd_base; /* Start of framebuffer memory */ -void *lcd_console_address; /* Start of console buffer */ - -short console_col; -short console_row; - /* configurable parameters */ #define ATMEL_LCDC_CVAL_DEFAULT 0xc8 #define ATMEL_LCDC_DMA_BURST_LEN 8 diff --git a/drivers/video/bcm2835.c b/drivers/video/bcm2835.c new file mode 100644 index 0000000..0c77d17 --- /dev/null +++ b/drivers/video/bcm2835.c @@ -0,0 +1,116 @@ +/* + * (C) Copyright 2012 Stephen Warren + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <common.h> +#include <lcd.h> +#include <asm/arch/mbox.h> +#include <asm/global_data.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* Global variables that lcd.c expects to exist */ +vidinfo_t panel_info; + +struct msg_query { + struct bcm2835_mbox_hdr hdr; + struct bcm2835_mbox_tag_physical_w_h physical_w_h; + u32 end_tag; +}; + +struct msg_setup { + struct bcm2835_mbox_hdr hdr; + struct bcm2835_mbox_tag_physical_w_h physical_w_h; + struct bcm2835_mbox_tag_virtual_w_h virtual_w_h; + struct bcm2835_mbox_tag_depth depth; + struct bcm2835_mbox_tag_pixel_order pixel_order; + struct bcm2835_mbox_tag_alpha_mode alpha_mode; + struct bcm2835_mbox_tag_virtual_offset virtual_offset; + struct bcm2835_mbox_tag_overscan overscan; + struct bcm2835_mbox_tag_allocate_buffer allocate_buffer; + u32 end_tag; +}; + +void lcd_ctrl_init(void *lcdbase) +{ + ALLOC_ALIGN_BUFFER(struct msg_query, msg_query, 1, 16); + ALLOC_ALIGN_BUFFER(struct msg_setup, msg_setup, 1, 16); + int ret; + u32 w, h; + + debug("bcm2835: Query resolution...\n"); + + BCM2835_MBOX_INIT_HDR(msg_query); + BCM2835_MBOX_INIT_TAG_NO_REQ(&msg_query->physical_w_h, + GET_PHYSICAL_W_H); + ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_query->hdr); + if (ret) { + printf("bcm2835: Could not query display resolution\n"); + /* FIXME: How to disable the LCD to prevent errors? hang()? */ + return; + } + + w = msg_query->physical_w_h.body.resp.width; + h = msg_query->physical_w_h.body.resp.height; + + debug("bcm2835: Setting up display for %d x %d\n", w, h); + + BCM2835_MBOX_INIT_HDR(msg_setup); + BCM2835_MBOX_INIT_TAG(&msg_setup->physical_w_h, SET_PHYSICAL_W_H); + msg_setup->physical_w_h.body.req.width = w; + msg_setup->physical_w_h.body.req.height = h; + BCM2835_MBOX_INIT_TAG(&msg_setup->virtual_w_h, SET_VIRTUAL_W_H); + msg_setup->virtual_w_h.body.req.width = w; + msg_setup->virtual_w_h.body.req.height = h; + BCM2835_MBOX_INIT_TAG(&msg_setup->depth, SET_DEPTH); + msg_setup->depth.body.req.bpp = 16; + BCM2835_MBOX_INIT_TAG(&msg_setup->pixel_order, SET_PIXEL_ORDER); + msg_setup->pixel_order.body.req.order = BCM2835_MBOX_PIXEL_ORDER_BGR; + BCM2835_MBOX_INIT_TAG(&msg_setup->alpha_mode, SET_ALPHA_MODE); + msg_setup->alpha_mode.body.req.alpha = BCM2835_MBOX_ALPHA_MODE_IGNORED; + BCM2835_MBOX_INIT_TAG(&msg_setup->virtual_offset, SET_VIRTUAL_OFFSET); + msg_setup->virtual_offset.body.req.x = 0; + msg_setup->virtual_offset.body.req.y = 0; + BCM2835_MBOX_INIT_TAG(&msg_setup->overscan, SET_OVERSCAN); + msg_setup->overscan.body.req.top = 0; + msg_setup->overscan.body.req.bottom = 0; + msg_setup->overscan.body.req.left = 0; + msg_setup->overscan.body.req.right = 0; + BCM2835_MBOX_INIT_TAG(&msg_setup->allocate_buffer, ALLOCATE_BUFFER); + msg_setup->allocate_buffer.body.req.alignment = 0x100; + + ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_setup->hdr); + if (ret) { + printf("bcm2835: Could not configure display\n"); + /* FIXME: How to disable the LCD to prevent errors? hang()? */ + return; + } + + w = msg_setup->physical_w_h.body.resp.width; + h = msg_setup->physical_w_h.body.resp.height; + + debug("bcm2835: Final resolution is %d x %d\n", w, h); + + panel_info.vl_col = w; + panel_info.vl_row = h; + panel_info.vl_bpix = LCD_COLOR16; + + gd->fb_base = msg_setup->allocate_buffer.body.resp.fb_address; +} + +void lcd_enable(void) +{ +} diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 26f673a..61e1058 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -1515,13 +1515,6 @@ int video_display_bitmap(ulong bmp_image, int x, int y) padded_line = (((width * bpp + 7) / 8) + 3) & ~0x3; - /* - * Just ignore elements which are completely beyond screen - * dimensions. - */ - if ((x >= VIDEO_VISIBLE_COLS) || (y >= VIDEO_VISIBLE_ROWS)) - return 0; - #ifdef CONFIG_SPLASH_SCREEN_ALIGN if (x == BMP_ALIGN_CENTER) x = max(0, (VIDEO_VISIBLE_COLS - width) / 2); @@ -1534,6 +1527,13 @@ int video_display_bitmap(ulong bmp_image, int x, int y) y = max(0, VIDEO_VISIBLE_ROWS - height + y + 1); #endif /* CONFIG_SPLASH_SCREEN_ALIGN */ + /* + * Just ignore elements which are completely beyond screen + * dimensions. + */ + if ((x >= VIDEO_VISIBLE_COLS) || (y >= VIDEO_VISIBLE_ROWS)) + return 0; + if ((x + width) > VIDEO_VISIBLE_COLS) width = VIDEO_VISIBLE_COLS - x; if ((y + height) > VIDEO_VISIBLE_ROWS) diff --git a/drivers/video/exynos_dp.c b/drivers/video/exynos_dp.c index d72fa56..87bb907 100644 --- a/drivers/video/exynos_dp.c +++ b/drivers/video/exynos_dp.c @@ -27,11 +27,21 @@ #include <asm/arch/cpu.h> #include <asm/arch/dp_info.h> #include <asm/arch/dp.h> +#include <fdtdec.h> +#include <libfdt.h> #include "exynos_dp_lowlevel.h" +DECLARE_GLOBAL_DATA_PTR; + static struct exynos_dp_platform_data *dp_pd; +void __exynos_set_dp_phy(unsigned int onoff) +{ +} +void exynos_set_dp_phy(unsigned int onoff) + __attribute__((weak, alias("__exynos_set_dp_phy"))); + static void exynos_dp_disp_info(struct edp_disp_info *disp_info) { disp_info->h_total = disp_info->h_res + disp_info->h_sync_width + @@ -853,6 +863,62 @@ static unsigned int exynos_dp_config_video(struct edp_device_info *edp_info) return ret; } +#ifdef CONFIG_OF_CONTROL +int exynos_dp_parse_dt(const void *blob, struct edp_device_info *edp_info) +{ + unsigned int node = fdtdec_next_compatible(blob, 0, + COMPAT_SAMSUNG_EXYNOS5_DP); + if (node <= 0) { + debug("exynos_dp: Can't get device node for dp\n"); + return -ENODEV; + } + + edp_info->disp_info.h_res = fdtdec_get_int(blob, node, + "samsung,h-res", 0); + edp_info->disp_info.h_sync_width = fdtdec_get_int(blob, node, + "samsung,h-sync-width", 0); + edp_info->disp_info.h_back_porch = fdtdec_get_int(blob, node, + "samsung,h-back-porch", 0); + edp_info->disp_info.h_front_porch = fdtdec_get_int(blob, node, + "samsung,h-front-porch", 0); + edp_info->disp_info.v_res = fdtdec_get_int(blob, node, + "samsung,v-res", 0); + edp_info->disp_info.v_sync_width = fdtdec_get_int(blob, node, + "samsung,v-sync-width", 0); + edp_info->disp_info.v_back_porch = fdtdec_get_int(blob, node, + "samsung,v-back-porch", 0); + edp_info->disp_info.v_front_porch = fdtdec_get_int(blob, node, + "samsung,v-front-porch", 0); + edp_info->disp_info.v_sync_rate = fdtdec_get_int(blob, node, + "samsung,v-sync-rate", 0); + + edp_info->lt_info.lt_status = fdtdec_get_int(blob, node, + "samsung,lt-status", 0); + + edp_info->video_info.master_mode = fdtdec_get_int(blob, node, + "samsung,master-mode", 0); + edp_info->video_info.bist_mode = fdtdec_get_int(blob, node, + "samsung,bist-mode", 0); + edp_info->video_info.bist_pattern = fdtdec_get_int(blob, node, + "samsung,bist-pattern", 0); + edp_info->video_info.h_sync_polarity = fdtdec_get_int(blob, node, + "samsung,h-sync-polarity", 0); + edp_info->video_info.v_sync_polarity = fdtdec_get_int(blob, node, + "samsung,v-sync-polarity", 0); + edp_info->video_info.interlaced = fdtdec_get_int(blob, node, + "samsung,interlaced", 0); + edp_info->video_info.color_space = fdtdec_get_int(blob, node, + "samsung,color-space", 0); + edp_info->video_info.dynamic_range = fdtdec_get_int(blob, node, + "samsung,dynamic-range", 0); + edp_info->video_info.ycbcr_coeff = fdtdec_get_int(blob, node, + "samsung,ycbcr-coeff", 0); + edp_info->video_info.color_depth = fdtdec_get_int(blob, node, + "samsung,color-depth", 0); + return 0; +} +#endif + unsigned int exynos_init_dp(void) { unsigned int ret; @@ -864,16 +930,22 @@ unsigned int exynos_init_dp(void) return -EFAULT; } +#ifdef CONFIG_OF_CONTROL + if (exynos_dp_parse_dt(gd->fdt_blob, edp_info)) + debug("unable to parse DP DT node\n"); +#else edp_info = dp_pd->edp_dev_info; if (edp_info == NULL) { debug("failed to get edp_info data.\n"); return -EFAULT; } +#endif + + exynos_dp_set_base_addr(); exynos_dp_disp_info(&edp_info->disp_info); - if (dp_pd->phy_enable) - dp_pd->phy_enable(1); + exynos_set_dp_phy(1); ret = exynos_dp_init_dp(); if (ret != EXYNOS_DP_SUCCESS) { diff --git a/drivers/video/exynos_dp_lowlevel.c b/drivers/video/exynos_dp_lowlevel.c index 7b54c80..748d9b8 100644 --- a/drivers/video/exynos_dp_lowlevel.c +++ b/drivers/video/exynos_dp_lowlevel.c @@ -25,11 +25,34 @@ #include <asm/arch/cpu.h> #include <asm/arch/dp_info.h> #include <asm/arch/dp.h> +#include <fdtdec.h> +#include <libfdt.h> + +/* Declare global data pointer */ +DECLARE_GLOBAL_DATA_PTR; + +struct exynos_dp *dp_regs; + +void exynos_dp_set_base_addr(void) +{ +#ifdef CONFIG_OF_CONTROL + unsigned int node = fdtdec_next_compatible(gd->fdt_blob, + 0, COMPAT_SAMSUNG_EXYNOS5_DP); + if (node <= 0) + debug("exynos_dp: Can't get device node for dp\n"); + + dp_regs = (struct exynos_dp *)fdtdec_get_addr(gd->fdt_blob, + node, "reg"); + if (dp_regs == NULL) + debug("Can't get the DP base address\n"); +#else + dp_regs = (struct exynos_dp *)samsung_get_base_dp(); +#endif +} static void exynos_dp_enable_video_input(unsigned int enable) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); reg = readl(&dp_regs->video_ctl1); reg &= ~VIDEO_EN_MASK; @@ -47,7 +70,6 @@ void exynos_dp_enable_video_bist(unsigned int enable) { /*enable video bist*/ unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); reg = readl(&dp_regs->video_ctl4); reg &= ~VIDEO_BIST_MASK; @@ -64,7 +86,6 @@ void exynos_dp_enable_video_bist(unsigned int enable) void exynos_dp_enable_video_mute(unsigned int enable) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); reg = readl(&dp_regs->video_ctl1); reg &= ~(VIDEO_MUTE_MASK); @@ -80,7 +101,6 @@ void exynos_dp_enable_video_mute(unsigned int enable) static void exynos_dp_init_analog_param(void) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /* * Set termination @@ -129,7 +149,6 @@ static void exynos_dp_init_analog_param(void) static void exynos_dp_init_interrupt(void) { - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /* Set interrupt registers to initial states */ /* @@ -158,7 +177,6 @@ static void exynos_dp_init_interrupt(void) void exynos_dp_reset(void) { unsigned int reg_func_1; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /*dp tx sw reset*/ writel(RESET_DP_TX, &dp_regs->tx_sw_reset); @@ -186,7 +204,6 @@ void exynos_dp_reset(void) void exynos_dp_enable_sw_func(unsigned int enable) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); reg = readl(&dp_regs->func_en1); reg &= ~(SW_FUNC_EN_N); @@ -202,7 +219,6 @@ void exynos_dp_enable_sw_func(unsigned int enable) unsigned int exynos_dp_set_analog_power_down(unsigned int block, u32 enable) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); reg = readl(&dp_regs->phy_pd); switch (block) { @@ -256,7 +272,6 @@ unsigned int exynos_dp_set_analog_power_down(unsigned int block, u32 enable) unsigned int exynos_dp_get_pll_lock_status(void) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); reg = readl(&dp_regs->debug_ctl); @@ -269,7 +284,6 @@ unsigned int exynos_dp_get_pll_lock_status(void) static void exynos_dp_set_pll_power(unsigned int enable) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); reg = readl(&dp_regs->pll_ctl); reg &= ~(DP_PLL_PD); @@ -285,7 +299,6 @@ int exynos_dp_init_analog_func(void) int ret = EXYNOS_DP_SUCCESS; unsigned int retry_cnt = 10; unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /*Power On All Analog block */ exynos_dp_set_analog_power_down(POWER_ALL, DP_DISABLE); @@ -335,7 +348,6 @@ int exynos_dp_init_analog_func(void) void exynos_dp_init_hpd(void) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /* Clear interrupts releated to Hot Plug Dectect */ reg = HOTPLUG_CHG | HPD_LOST | PLUG; @@ -354,7 +366,6 @@ void exynos_dp_init_hpd(void) static inline void exynos_dp_reset_aux(void) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /* Disable AUX channel module */ reg = readl(&dp_regs->func_en2); @@ -367,7 +378,6 @@ static inline void exynos_dp_reset_aux(void) void exynos_dp_init_aux(void) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /* Clear inerrupts related to AUX channel */ reg = RPLY_RECEIV | AUX_ERR; @@ -395,7 +405,6 @@ void exynos_dp_init_aux(void) void exynos_dp_config_interrupt(void) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /* 0: mask, 1: unmask */ reg = COMMON_INT_MASK_1; @@ -419,7 +428,6 @@ void exynos_dp_config_interrupt(void) unsigned int exynos_dp_get_plug_in_status(void) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); reg = readl(&dp_regs->sys_ctl3); if (reg & HPD_STATUS) @@ -449,7 +457,6 @@ unsigned int exynos_dp_start_aux_transaction(void) unsigned int reg; unsigned int ret = 0; unsigned int retry_cnt; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /* Enable AUX CH operation */ reg = readl(&dp_regs->aux_ch_ctl2); @@ -498,7 +505,6 @@ unsigned int exynos_dp_write_byte_to_dpcd(unsigned int reg_addr, unsigned char data) { unsigned int reg, ret; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /* Clear AUX CH data buffer */ reg = BUF_CLR; @@ -539,7 +545,6 @@ unsigned int exynos_dp_read_byte_from_dpcd(unsigned int reg_addr, { unsigned int reg; int retval; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /* Clear AUX CH data buffer */ reg = BUF_CLR; @@ -583,7 +588,6 @@ unsigned int exynos_dp_write_bytes_to_dpcd(unsigned int reg_addr, unsigned int cur_data_idx; unsigned int retry_cnt; unsigned int ret = 0; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /* Clear AUX CH data buffer */ reg = BUF_CLR; @@ -649,7 +653,6 @@ unsigned int exynos_dp_read_bytes_from_dpcd(unsigned int reg_addr, unsigned int cur_data_idx; unsigned int retry_cnt; unsigned int ret = 0; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /* Clear AUX CH data buffer */ reg = BUF_CLR; @@ -711,7 +714,6 @@ int exynos_dp_select_i2c_device(unsigned int device_addr, { unsigned int reg; int retval; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /* Set EDID device address */ reg = device_addr; @@ -746,7 +748,6 @@ int exynos_dp_read_byte_from_i2c(unsigned int device_addr, unsigned int reg; int i; int retval; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); for (i = 0; i < 10; i++) { /* Clear AUX CH data buffer */ @@ -790,7 +791,6 @@ int exynos_dp_read_bytes_from_i2c(unsigned int device_addr, unsigned int cur_data_idx; unsigned int defer = 0; int retval = 0; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); for (i = 0; i < count; i += 16) { /* use 16 burst */ for (j = 0; j < 100; j++) { @@ -854,7 +854,6 @@ int exynos_dp_read_bytes_from_i2c(unsigned int device_addr, void exynos_dp_reset_macro(void) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); reg = readl(&dp_regs->phy_test); reg |= MACRO_RST; @@ -870,7 +869,6 @@ void exynos_dp_reset_macro(void) void exynos_dp_set_link_bandwidth(unsigned char bwtype) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); reg = (unsigned int)bwtype; @@ -883,7 +881,6 @@ unsigned char exynos_dp_get_link_bandwidth(void) { unsigned char ret; unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); reg = readl(&dp_regs->link_bw_set); ret = (unsigned char)reg; @@ -894,7 +891,6 @@ unsigned char exynos_dp_get_link_bandwidth(void) void exynos_dp_set_lane_count(unsigned char count) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); reg = (unsigned int)count; @@ -906,7 +902,6 @@ void exynos_dp_set_lane_count(unsigned char count) unsigned int exynos_dp_get_lane_count(void) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); reg = readl(&dp_regs->lane_count_set); @@ -915,7 +910,6 @@ unsigned int exynos_dp_get_lane_count(void) unsigned char exynos_dp_get_lanex_pre_emphasis(unsigned char lanecnt) { - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); unsigned int reg_list[DP_LANE_CNT_4] = { (unsigned int)&dp_regs->ln0_link_training_ctl, (unsigned int)&dp_regs->ln1_link_training_ctl, @@ -929,7 +923,6 @@ unsigned char exynos_dp_get_lanex_pre_emphasis(unsigned char lanecnt) void exynos_dp_set_lanex_pre_emphasis(unsigned char request_val, unsigned char lanecnt) { - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); unsigned int reg_list[DP_LANE_CNT_4] = { (unsigned int)&dp_regs->ln0_link_training_ctl, (unsigned int)&dp_regs->ln1_link_training_ctl, @@ -944,7 +937,6 @@ void exynos_dp_set_lane_pre_emphasis(unsigned int level, unsigned char lanecnt) { unsigned char i; unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); unsigned int reg_list[DP_LANE_CNT_4] = { (unsigned int)&dp_regs->ln0_link_training_ctl, (unsigned int)&dp_regs->ln1_link_training_ctl, @@ -967,7 +959,6 @@ void exynos_dp_set_lane_pre_emphasis(unsigned int level, unsigned char lanecnt) void exynos_dp_set_training_pattern(unsigned int pattern) { unsigned int reg = 0; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); switch (pattern) { case PRBS7: @@ -996,7 +987,6 @@ void exynos_dp_set_training_pattern(unsigned int pattern) void exynos_dp_enable_enhanced_mode(unsigned char enable) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); reg = readl(&dp_regs->sys_ctl4); reg &= ~ENHANCED; @@ -1010,7 +1000,6 @@ void exynos_dp_enable_enhanced_mode(unsigned char enable) void exynos_dp_enable_scrambling(unsigned int enable) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); reg = readl(&dp_regs->training_ptn_set); reg &= ~(SCRAMBLING_DISABLE); @@ -1024,7 +1013,6 @@ void exynos_dp_enable_scrambling(unsigned int enable) int exynos_dp_init_video(void) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /* Clear VID_CLK_CHG[1] and VID_FORMAT_CHG[3] and VSYNC_DET[7] */ reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG; @@ -1040,7 +1028,6 @@ int exynos_dp_init_video(void) void exynos_dp_config_video_slave_mode(struct edp_video_info *video_info) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /* Video Slave mode setting */ reg = readl(&dp_regs->func_en1); @@ -1074,7 +1061,6 @@ void exynos_dp_config_video_slave_mode(struct edp_video_info *video_info) void exynos_dp_set_video_color_format(struct edp_video_info *video_info) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /* Configure the input color depth, color space, dynamic range */ reg = (video_info->dynamic_range << IN_D_RANGE_SHIFT) | @@ -1097,7 +1083,6 @@ int exynos_dp_config_video_bist(struct edp_device_info *edp_info) unsigned int reg; unsigned int bist_type = 0; struct edp_video_info video_info = edp_info->video_info; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /* For master mode, you don't need to set the video format */ if (video_info.master_mode == 0) { @@ -1186,7 +1171,6 @@ int exynos_dp_config_video_bist(struct edp_device_info *edp_info) unsigned int exynos_dp_is_slave_video_stream_clock_on(void) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /* Update Video stream clk detect status */ reg = readl(&dp_regs->sys_ctl1); @@ -1206,7 +1190,6 @@ void exynos_dp_set_video_cr_mn(unsigned int type, unsigned int m_value, unsigned int n_value) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); if (type == REGISTER_M) { reg = readl(&dp_regs->sys_ctl4); @@ -1235,7 +1218,6 @@ void exynos_dp_set_video_cr_mn(unsigned int type, unsigned int m_value, void exynos_dp_set_video_timing_mode(unsigned int type) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); reg = readl(&dp_regs->video_ctl10); reg &= ~FORMAT_SEL; @@ -1249,7 +1231,6 @@ void exynos_dp_set_video_timing_mode(unsigned int type) void exynos_dp_enable_video_master(unsigned int enable) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); reg = readl(&dp_regs->soc_general_ctl); if (enable) { @@ -1266,7 +1247,6 @@ void exynos_dp_enable_video_master(unsigned int enable) void exynos_dp_start_video(void) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /* Enable Video input and disable Mute */ reg = readl(&dp_regs->video_ctl1); @@ -1277,7 +1257,6 @@ void exynos_dp_start_video(void) unsigned int exynos_dp_is_video_stream_on(void) { unsigned int reg; - struct exynos_dp *dp_regs = (struct exynos_dp *)samsung_get_base_dp(); /* Update STRM_VALID */ reg = readl(&dp_regs->sys_ctl3); diff --git a/drivers/video/exynos_dp_lowlevel.h b/drivers/video/exynos_dp_lowlevel.h index a041a7a..2c0ae12 100644 --- a/drivers/video/exynos_dp_lowlevel.h +++ b/drivers/video/exynos_dp_lowlevel.h @@ -76,5 +76,6 @@ void exynos_dp_set_video_timing_mode(unsigned int type); void exynos_dp_enable_video_master(unsigned int enable); void exynos_dp_start_video(void); unsigned int exynos_dp_is_video_stream_on(void); +void exynos_dp_set_base_addr(void); #endif /* _EXYNOS_DP_LOWLEVEL_H */ diff --git a/drivers/video/exynos_fb.c b/drivers/video/exynos_fb.c index ee0ed06..ed0823b 100644 --- a/drivers/video/exynos_fb.c +++ b/drivers/video/exynos_fb.c @@ -23,6 +23,8 @@ #include <config.h> #include <common.h> #include <lcd.h> +#include <fdtdec.h> +#include <libfdt.h> #include <asm/io.h> #include <asm/arch/cpu.h> #include <asm/arch/clock.h> @@ -30,21 +32,28 @@ #include <asm/arch/mipi_dsim.h> #include <asm/arch/dp_info.h> #include <asm/arch/system.h> +#include <asm-generic/errno.h> #include "exynos_fb.h" -int lcd_line_length; -int lcd_color_fg; -int lcd_color_bg; - -void *lcd_base; -void *lcd_console_address; - -short console_col; -short console_row; +DECLARE_GLOBAL_DATA_PTR; static unsigned int panel_width, panel_height; +/* + * board_init_f(arch/arm/lib/board.c) calls lcd_setmem() which needs + * panel_info.vl_col, panel_info.vl_row and panel_info.vl_bpix to reserve + * FB memory at a very early stage, i.e even before exynos_fimd_parse_dt() + * is called. So, we are forced to statically assign it. + */ +#ifdef CONFIG_OF_CONTROL +vidinfo_t panel_info = { + .vl_col = LCD_XRES, + .vl_row = LCD_YRES, + .vl_bpix = LCD_COLOR16, +}; +#endif + static void exynos_lcd_init_mem(void *lcdbase, vidinfo_t *vid) { unsigned long palette_size; @@ -52,11 +61,9 @@ static void exynos_lcd_init_mem(void *lcdbase, vidinfo_t *vid) fb_size = vid->vl_row * vid->vl_col * (NBITS(vid->vl_bpix) >> 3); - lcd_base = lcdbase; - palette_size = NBITS(vid->vl_bpix) == 8 ? 256 : 16; - exynos_fimd_lcd_init_mem((unsigned long)lcd_base, + exynos_fimd_lcd_init_mem((unsigned long)lcdbase, (unsigned long)fb_size, palette_size); } @@ -93,47 +100,226 @@ static void draw_logo(void) } #endif +void __exynos_cfg_lcd_gpio(void) +{ +} +void exynos_cfg_lcd_gpio(void) + __attribute__((weak, alias("__exynos_cfg_lcd_gpio"))); + +void __exynos_backlight_on(unsigned int onoff) +{ +} +void exynos_backlight_on(unsigned int onoff) + __attribute__((weak, alias("__exynos_cfg_lcd_gpio"))); + +void __exynos_reset_lcd(void) +{ +} +void exynos_reset_lcd(void) + __attribute__((weak, alias("__exynos_reset_lcd"))); + +void __exynos_lcd_power_on(void) +{ +} +void exynos_lcd_power_on(void) + __attribute__((weak, alias("__exynos_lcd_power_on"))); + +void __exynos_cfg_ldo(void) +{ +} +void exynos_cfg_ldo(void) + __attribute__((weak, alias("__exynos_cfg_ldo"))); + +void __exynos_enable_ldo(unsigned int onoff) +{ +} +void exynos_enable_ldo(unsigned int onoff) + __attribute__((weak, alias("__exynos_enable_ldo"))); + +void __exynos_backlight_reset(void) +{ +} +void exynos_backlight_reset(void) + __attribute__((weak, alias("__exynos_backlight_reset"))); + static void lcd_panel_on(vidinfo_t *vid) { udelay(vid->init_delay); - if (vid->backlight_reset) - vid->backlight_reset(); + exynos_backlight_reset(); - if (vid->cfg_gpio) - vid->cfg_gpio(); + exynos_cfg_lcd_gpio(); - if (vid->lcd_power_on) - vid->lcd_power_on(); + exynos_lcd_power_on(); udelay(vid->power_on_delay); if (vid->dp_enabled) exynos_init_dp(); - if (vid->reset_lcd) { - vid->reset_lcd(); - udelay(vid->reset_delay); - } + exynos_reset_lcd(); + + udelay(vid->reset_delay); - if (vid->backlight_on) - vid->backlight_on(1); + exynos_backlight_on(1); - if (vid->cfg_ldo) - vid->cfg_ldo(); + exynos_cfg_ldo(); - if (vid->enable_ldo) - vid->enable_ldo(1); + exynos_enable_ldo(1); if (vid->mipi_enabled) exynos_mipi_dsi_init(); } +#ifdef CONFIG_OF_CONTROL +int exynos_fimd_parse_dt(const void *blob) +{ + unsigned int node; + node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS_FIMD); + if (node <= 0) { + debug("exynos_fb: Can't get device node for fimd\n"); + return -ENODEV; + } + + panel_info.vl_col = fdtdec_get_int(blob, node, "samsung,vl-col", 0); + if (panel_info.vl_col == 0) { + debug("Can't get XRES\n"); + return -ENXIO; + } + + panel_info.vl_row = fdtdec_get_int(blob, node, "samsung,vl-row", 0); + if (panel_info.vl_row == 0) { + debug("Can't get YRES\n"); + return -ENXIO; + } + + panel_info.vl_width = fdtdec_get_int(blob, node, + "samsung,vl-width", 0); + + panel_info.vl_height = fdtdec_get_int(blob, node, + "samsung,vl-height", 0); + + panel_info.vl_freq = fdtdec_get_int(blob, node, "samsung,vl-freq", 0); + if (panel_info.vl_freq == 0) { + debug("Can't get refresh rate\n"); + return -ENXIO; + } + + if (fdtdec_get_bool(blob, node, "samsung,vl-clkp")) + panel_info.vl_clkp = CONFIG_SYS_LOW; + + if (fdtdec_get_bool(blob, node, "samsung,vl-oep")) + panel_info.vl_oep = CONFIG_SYS_LOW; + + if (fdtdec_get_bool(blob, node, "samsung,vl-hsp")) + panel_info.vl_hsp = CONFIG_SYS_LOW; + + if (fdtdec_get_bool(blob, node, "samsung,vl-vsp")) + panel_info.vl_vsp = CONFIG_SYS_LOW; + + if (fdtdec_get_bool(blob, node, "samsung,vl-dp")) + panel_info.vl_dp = CONFIG_SYS_LOW; + + panel_info.vl_bpix = fdtdec_get_int(blob, node, "samsung,vl-bpix", 0); + if (panel_info.vl_bpix == 0) { + debug("Can't get bits per pixel\n"); + return -ENXIO; + } + + panel_info.vl_hspw = fdtdec_get_int(blob, node, "samsung,vl-hspw", 0); + if (panel_info.vl_hspw == 0) { + debug("Can't get hsync width\n"); + return -ENXIO; + } + + panel_info.vl_hfpd = fdtdec_get_int(blob, node, "samsung,vl-hfpd", 0); + if (panel_info.vl_hfpd == 0) { + debug("Can't get right margin\n"); + return -ENXIO; + } + + panel_info.vl_hbpd = (u_char)fdtdec_get_int(blob, node, + "samsung,vl-hbpd", 0); + if (panel_info.vl_hbpd == 0) { + debug("Can't get left margin\n"); + return -ENXIO; + } + + panel_info.vl_vspw = (u_char)fdtdec_get_int(blob, node, + "samsung,vl-vspw", 0); + if (panel_info.vl_vspw == 0) { + debug("Can't get vsync width\n"); + return -ENXIO; + } + + panel_info.vl_vfpd = fdtdec_get_int(blob, node, + "samsung,vl-vfpd", 0); + if (panel_info.vl_vfpd == 0) { + debug("Can't get lower margin\n"); + return -ENXIO; + } + + panel_info.vl_vbpd = fdtdec_get_int(blob, node, "samsung,vl-vbpd", 0); + if (panel_info.vl_vbpd == 0) { + debug("Can't get upper margin\n"); + return -ENXIO; + } + + panel_info.vl_cmd_allow_len = fdtdec_get_int(blob, node, + "samsung,vl-cmd-allow-len", 0); + + panel_info.win_id = fdtdec_get_int(blob, node, "samsung,winid", 0); + panel_info.init_delay = fdtdec_get_int(blob, node, + "samsung,init-delay", 0); + panel_info.power_on_delay = fdtdec_get_int(blob, node, + "samsung,power-on-delay", 0); + panel_info.reset_delay = fdtdec_get_int(blob, node, + "samsung,reset-delay", 0); + panel_info.interface_mode = fdtdec_get_int(blob, node, + "samsung,interface-mode", 0); + panel_info.mipi_enabled = fdtdec_get_int(blob, node, + "samsung,mipi-enabled", 0); + panel_info.dp_enabled = fdtdec_get_int(blob, node, + "samsung,dp-enabled", 0); + panel_info.cs_setup = fdtdec_get_int(blob, node, + "samsung,cs-setup", 0); + panel_info.wr_setup = fdtdec_get_int(blob, node, + "samsung,wr-setup", 0); + panel_info.wr_act = fdtdec_get_int(blob, node, "samsung,wr-act", 0); + panel_info.wr_hold = fdtdec_get_int(blob, node, "samsung,wr-hold", 0); + + panel_info.logo_on = fdtdec_get_int(blob, node, "samsung,logo-on", 0); + if (panel_info.logo_on) { + panel_info.logo_width = fdtdec_get_int(blob, node, + "samsung,logo-width", 0); + panel_info.logo_height = fdtdec_get_int(blob, node, + "samsung,logo-height", 0); + panel_info.logo_addr = fdtdec_get_int(blob, node, + "samsung,logo-addr", 0); + } + + panel_info.rgb_mode = fdtdec_get_int(blob, node, + "samsung,rgb-mode", 0); + panel_info.pclk_name = fdtdec_get_int(blob, node, + "samsung,pclk-name", 0); + panel_info.sclk_div = fdtdec_get_int(blob, node, + "samsung,sclk-div", 0); + panel_info.dual_lcd_enabled = fdtdec_get_int(blob, node, + "samsung,dual-lcd-enabled", 0); + + return 0; +} +#endif + void lcd_ctrl_init(void *lcdbase) { set_system_display_ctrl(); set_lcd_clk(); +#ifdef CONFIG_OF_CONTROL + if (exynos_fimd_parse_dt(gd->fdt_blob)) + debug("Can't get proper panel info\n"); +#endif /* initialize parameters which is specific to panel. */ init_panel_info(&panel_info); @@ -148,7 +334,7 @@ void lcd_ctrl_init(void *lcdbase) void lcd_enable(void) { if (panel_info.logo_on) { - memset(lcd_base, 0, panel_width * panel_height * + memset((void *) gd->fb_base, 0, panel_width * panel_height * (NBITS(panel_info.vl_bpix) >> 3)); #ifdef CONFIG_CMD_BMP draw_logo(); diff --git a/drivers/video/exynos_fimd.c b/drivers/video/exynos_fimd.c index 2efe6a6..3359949 100644 --- a/drivers/video/exynos_fimd.c +++ b/drivers/video/exynos_fimd.c @@ -25,13 +25,18 @@ #include <asm/io.h> #include <lcd.h> #include <div64.h> +#include <fdtdec.h> +#include <libfdt.h> #include <asm/arch/clk.h> #include <asm/arch/clock.h> #include <asm/arch/cpu.h> #include "exynos_fb.h" +DECLARE_GLOBAL_DATA_PTR; + static unsigned long *lcd_base_addr; static vidinfo_t *pvid; +static struct exynos_fb *fimd_ctrl; void exynos_fimd_lcd_init_mem(u_long screen_base, u_long fb_size, u_long palette_size) @@ -41,8 +46,6 @@ void exynos_fimd_lcd_init_mem(u_long screen_base, u_long fb_size, static void exynos_fimd_set_dualrgb(unsigned int enabled) { - struct exynos_fb *fimd_ctrl = - (struct exynos_fb *)samsung_get_base_fimd(); unsigned int cfg = 0; if (enabled) { @@ -59,9 +62,6 @@ static void exynos_fimd_set_dualrgb(unsigned int enabled) static void exynos_fimd_set_dp_clkcon(unsigned int enabled) { - - struct exynos_fb *fimd_ctrl = - (struct exynos_fb *)samsung_get_base_fimd(); unsigned int cfg = 0; if (enabled) @@ -73,8 +73,6 @@ static void exynos_fimd_set_dp_clkcon(unsigned int enabled) static void exynos_fimd_set_par(unsigned int win_id) { unsigned int cfg = 0; - struct exynos_fb *fimd_ctrl = - (struct exynos_fb *)samsung_get_base_fimd(); /* set window control */ cfg = readl((unsigned int)&fimd_ctrl->wincon0 + @@ -126,8 +124,6 @@ static void exynos_fimd_set_par(unsigned int win_id) static void exynos_fimd_set_buffer_address(unsigned int win_id) { unsigned long start_addr, end_addr; - struct exynos_fb *fimd_ctrl = - (struct exynos_fb *)samsung_get_base_fimd(); start_addr = (unsigned long)lcd_base_addr; end_addr = start_addr + ((pvid->vl_col * (NBITS(pvid->vl_bpix) / 8)) * @@ -144,8 +140,6 @@ static void exynos_fimd_set_clock(vidinfo_t *pvid) unsigned int cfg = 0, div = 0, remainder, remainder_div; unsigned long pixel_clock; unsigned long long src_clock; - struct exynos_fb *fimd_ctrl = - (struct exynos_fb *)samsung_get_base_fimd(); if (pvid->dual_lcd_enabled) { pixel_clock = pvid->vl_freq * @@ -197,8 +191,6 @@ static void exynos_fimd_set_clock(vidinfo_t *pvid) void exynos_set_trigger(void) { unsigned int cfg = 0; - struct exynos_fb *fimd_ctrl = - (struct exynos_fb *)samsung_get_base_fimd(); cfg = readl(&fimd_ctrl->trigcon); @@ -211,8 +203,6 @@ int exynos_is_i80_frame_done(void) { unsigned int cfg = 0; int status; - struct exynos_fb *fimd_ctrl = - (struct exynos_fb *)samsung_get_base_fimd(); cfg = readl(&fimd_ctrl->trigcon); @@ -226,8 +216,6 @@ int exynos_is_i80_frame_done(void) static void exynos_fimd_lcd_on(void) { unsigned int cfg = 0; - struct exynos_fb *fimd_ctrl = - (struct exynos_fb *)samsung_get_base_fimd(); /* display on */ cfg = readl(&fimd_ctrl->vidcon0); @@ -238,8 +226,6 @@ static void exynos_fimd_lcd_on(void) static void exynos_fimd_window_on(unsigned int win_id) { unsigned int cfg = 0; - struct exynos_fb *fimd_ctrl = - (struct exynos_fb *)samsung_get_base_fimd(); /* enable window */ cfg = readl((unsigned int)&fimd_ctrl->wincon0 + @@ -256,8 +242,6 @@ static void exynos_fimd_window_on(unsigned int win_id) void exynos_fimd_lcd_off(void) { unsigned int cfg = 0; - struct exynos_fb *fimd_ctrl = - (struct exynos_fb *)samsung_get_base_fimd(); cfg = readl(&fimd_ctrl->vidcon0); cfg &= (EXYNOS_VIDCON0_ENVID_DISABLE | EXYNOS_VIDCON0_ENVID_F_DISABLE); @@ -267,8 +251,6 @@ void exynos_fimd_lcd_off(void) void exynos_fimd_window_off(unsigned int win_id) { unsigned int cfg = 0; - struct exynos_fb *fimd_ctrl = - (struct exynos_fb *)samsung_get_base_fimd(); cfg = readl((unsigned int)&fimd_ctrl->wincon0 + EXYNOS_WINCON(win_id)); @@ -286,8 +268,20 @@ void exynos_fimd_lcd_init(vidinfo_t *vid) { unsigned int cfg = 0, rgb_mode; unsigned int offset; - struct exynos_fb *fimd_ctrl = - (struct exynos_fb *)samsung_get_base_fimd(); +#ifdef CONFIG_OF_CONTROL + unsigned int node; + + node = fdtdec_next_compatible(gd->fdt_blob, + 0, COMPAT_SAMSUNG_EXYNOS_FIMD); + if (node <= 0) + debug("exynos_fb: Can't get device node for fimd\n"); + + fimd_ctrl = (struct exynos_fb *)fdtdec_get_addr(gd->fdt_blob, + node, "reg"); + if (fimd_ctrl == NULL) + debug("Can't get the FIMD base address\n"); +#endif + fimd_ctrl = (struct exynos_fb *)samsung_get_base_fimd(); offset = exynos_fimd_get_base_offset(); diff --git a/drivers/video/mpc8xx_lcd.c b/drivers/video/mpc8xx_lcd.c new file mode 100644 index 0000000..f0f728e --- /dev/null +++ b/drivers/video/mpc8xx_lcd.c @@ -0,0 +1,564 @@ +/* + * (C) Copyright 2001-2002 + * Wolfgang Denk, DENX Software Engineering -- wd@denx.de + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/************************************************************************/ +/* ** HEADER FILES */ +/************************************************************************/ + +/* #define DEBUG */ + +#include <config.h> +#include <common.h> +#include <command.h> +#include <watchdog.h> +#include <version.h> +#include <stdarg.h> +#include <lcdvideo.h> +#include <linux/types.h> +#include <stdio_dev.h> +#if defined(CONFIG_POST) +#include <post.h> +#endif +#include <lcd.h> + +#ifdef CONFIG_LCD + +/************************************************************************/ +/* ** CONFIG STUFF -- should be moved to board config file */ +/************************************************************************/ +#ifndef CONFIG_LCD_INFO +#define CONFIG_LCD_INFO /* Display Logo, (C) and system info */ +#endif + +#if defined(CONFIG_V37) || defined(CONFIG_EDT32F10) +#undef CONFIG_LCD_LOGO +#undef CONFIG_LCD_INFO +#endif + +/*----------------------------------------------------------------------*/ +#ifdef CONFIG_KYOCERA_KCS057QV1AJ +/* + * Kyocera KCS057QV1AJ-G23. Passive, color, single scan. + */ +#define LCD_BPP LCD_COLOR4 + +vidinfo_t panel_info = { + 640, 480, 132, 99, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, + LCD_BPP, 1, 0, 1, 0, 5, 0, 0, 0 + /* wbl, vpw, lcdac, wbf */ +}; +#endif /* CONFIG_KYOCERA_KCS057QV1AJ */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +#ifdef CONFIG_HITACHI_SP19X001_Z1A +/* + * Hitachi SP19X001-. Active, color, single scan. + */ +vidinfo_t panel_info = { + 640, 480, 154, 116, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, + LCD_COLOR8, 1, 0, 1, 0, 0, 0, 0, 0 + /* wbl, vpw, lcdac, wbf */ +}; +#endif /* CONFIG_HITACHI_SP19X001_Z1A */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +#ifdef CONFIG_NEC_NL6448AC33 +/* + * NEC NL6448AC33-18. Active, color, single scan. + */ +vidinfo_t panel_info = { + 640, 480, 132, 99, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW, CONFIG_SYS_LOW, CONFIG_SYS_HIGH, + 3, 0, 0, 1, 1, 144, 2, 0, 33 + /* wbl, vpw, lcdac, wbf */ +}; +#endif /* CONFIG_NEC_NL6448AC33 */ +/*----------------------------------------------------------------------*/ + +#ifdef CONFIG_NEC_NL6448BC20 +/* + * NEC NL6448BC20-08. 6.5", 640x480. Active, color, single scan. + */ +vidinfo_t panel_info = { + 640, 480, 132, 99, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW, CONFIG_SYS_LOW, CONFIG_SYS_HIGH, + 3, 0, 0, 1, 1, 144, 2, 0, 33 + /* wbl, vpw, lcdac, wbf */ +}; +#endif /* CONFIG_NEC_NL6448BC20 */ +/*----------------------------------------------------------------------*/ + +#ifdef CONFIG_NEC_NL6448BC33_54 +/* + * NEC NL6448BC33-54. 10.4", 640x480. Active, color, single scan. + */ +vidinfo_t panel_info = { + 640, 480, 212, 158, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW, CONFIG_SYS_LOW, CONFIG_SYS_HIGH, + 3, 0, 0, 1, 1, 144, 2, 0, 33 + /* wbl, vpw, lcdac, wbf */ +}; +#endif /* CONFIG_NEC_NL6448BC33_54 */ +/*----------------------------------------------------------------------*/ + +#ifdef CONFIG_SHARP_LQ104V7DS01 +/* + * SHARP LQ104V7DS01. 6.5", 640x480. Active, color, single scan. + */ +vidinfo_t panel_info = { + 640, 480, 132, 99, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW, CONFIG_SYS_LOW, CONFIG_SYS_LOW, + 3, 0, 0, 1, 1, 25, 1, 0, 33 + /* wbl, vpw, lcdac, wbf */ +}; +#endif /* CONFIG_SHARP_LQ104V7DS01 */ +/*----------------------------------------------------------------------*/ + +#ifdef CONFIG_SHARP_16x9 +/* + * Sharp 320x240. Active, color, single scan. It isn't 16x9, and I am + * not sure what it is....... + */ +vidinfo_t panel_info = { + 320, 240, 0, 0, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, + 3, 0, 0, 1, 1, 15, 4, 0, 3 +}; +#endif /* CONFIG_SHARP_16x9 */ +/*----------------------------------------------------------------------*/ + +#ifdef CONFIG_SHARP_LQ057Q3DC02 +/* + * Sharp LQ057Q3DC02 display. Active, color, single scan. + */ +#undef LCD_DF +#define LCD_DF 12 + +vidinfo_t panel_info = { + 320, 240, 0, 0, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW, CONFIG_SYS_LOW, CONFIG_SYS_HIGH, + 3, 0, 0, 1, 1, 15, 4, 0, 3 + /* wbl, vpw, lcdac, wbf */ +}; +#define CONFIG_LCD_INFO_BELOW_LOGO +#endif /* CONFIG_SHARP_LQ057Q3DC02 */ +/*----------------------------------------------------------------------*/ + +#ifdef CONFIG_SHARP_LQ64D341 +/* + * Sharp LQ64D341 display, 640x480. Active, color, single scan. + */ +vidinfo_t panel_info = { + 640, 480, 0, 0, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW, CONFIG_SYS_LOW, CONFIG_SYS_HIGH, + 3, 0, 0, 1, 1, 128, 16, 0, 32 + /* wbl, vpw, lcdac, wbf */ +}; +#endif /* CONFIG_SHARP_LQ64D341 */ + +#ifdef CONFIG_SHARP_LQ065T9DR51U +/* + * Sharp LQ065T9DR51U display, 400x240. Active, color, single scan. + */ +vidinfo_t panel_info = { + 400, 240, 143, 79, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, + 3, 0, 0, 1, 1, 248, 4, 0, 35 + /* wbl, vpw, lcdac, wbf */ +}; +#define CONFIG_LCD_INFO_BELOW_LOGO +#endif /* CONFIG_SHARP_LQ065T9DR51U */ + +#ifdef CONFIG_SHARP_LQ084V1DG21 +/* + * Sharp LQ084V1DG21 display, 640x480. Active, color, single scan. + */ +vidinfo_t panel_info = { + 640, 480, 171, 129, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW, CONFIG_SYS_LOW, CONFIG_SYS_LOW, + 3, 0, 0, 1, 1, 160, 3, 0, 48 + /* wbl, vpw, lcdac, wbf */ +}; +#endif /* CONFIG_SHARP_LQ084V1DG21 */ + +/*----------------------------------------------------------------------*/ + +#ifdef CONFIG_HLD1045 +/* + * HLD1045 display, 640x480. Active, color, single scan. + */ +vidinfo_t panel_info = { + 640, 480, 0, 0, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW, CONFIG_SYS_LOW, CONFIG_SYS_HIGH, + 3, 0, 0, 1, 1, 160, 3, 0, 48 + /* wbl, vpw, lcdac, wbf */ +}; +#endif /* CONFIG_HLD1045 */ +/*----------------------------------------------------------------------*/ + +#ifdef CONFIG_PRIMEVIEW_V16C6448AC +/* + * Prime View V16C6448AC + */ +vidinfo_t panel_info = { + 640, 480, 130, 98, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW, CONFIG_SYS_LOW, CONFIG_SYS_HIGH, + 3, 0, 0, 1, 1, 144, 2, 0, 35 + /* wbl, vpw, lcdac, wbf */ +}; +#endif /* CONFIG_PRIMEVIEW_V16C6448AC */ + +/*----------------------------------------------------------------------*/ + +#ifdef CONFIG_OPTREX_BW +/* + * Optrex CBL50840-2 NF-FW 99 22 M5 + * or + * Hitachi LMG6912RPFC-00T + * or + * Hitachi SP14Q002 + * + * 320x240. Black & white. + */ +#define OPTREX_BPP 0 /* 0 - monochrome, 1 bpp */ + /* 1 - 4 grey levels, 2 bpp */ + /* 2 - 16 grey levels, 4 bpp */ +vidinfo_t panel_info = { + 320, 240, 0, 0, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW, + OPTREX_BPP, 0, 0, 0, 0, 0, 0, 0, 0, 4 +}; +#endif /* CONFIG_OPTREX_BW */ + +/*-----------------------------------------------------------------*/ +#ifdef CONFIG_EDT32F10 +/* + * Emerging Display Technologies 320x240. Passive, monochrome, single scan. + */ +#define LCD_BPP LCD_MONOCHROME +#define LCD_DF 10 + +vidinfo_t panel_info = { + 320, 240, 0, 0, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_HIGH, CONFIG_SYS_LOW, + LCD_BPP, 0, 0, 0, 0, 33, 0, 0, 0 +}; +#endif + +/************************************************************************/ +/* ----------------- chipset specific functions ----------------------- */ +/************************************************************************/ + +/* + * Calculate fb size for VIDEOLFB_ATAG. + */ +ulong calc_fbsize (void) +{ + ulong size; + int line_length = (panel_info.vl_col * NBITS (panel_info.vl_bpix)) / 8; + + size = line_length * panel_info.vl_row; + + return size; +} + +void lcd_ctrl_init (void *lcdbase) +{ + volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; + volatile lcd823_t *lcdp = &immr->im_lcd; + + uint lccrtmp; + uint lchcr_hpc_tmp; + + /* Initialize the LCD control register according to the LCD + * parameters defined. We do everything here but enable + * the controller. + */ + +#ifdef CONFIG_RPXLITE + /* This is special for RPXlite_DW Software Development Platform **[Sam]** */ + panel_info.vl_dp = CONFIG_SYS_LOW; +#endif + + lccrtmp = LCDBIT (LCCR_BNUM_BIT, + (((panel_info.vl_row * panel_info.vl_col) * (1 << LCD_BPP)) / 128)); + + lccrtmp |= LCDBIT (LCCR_CLKP_BIT, panel_info.vl_clkp) | + LCDBIT (LCCR_OEP_BIT, panel_info.vl_oep) | + LCDBIT (LCCR_HSP_BIT, panel_info.vl_hsp) | + LCDBIT (LCCR_VSP_BIT, panel_info.vl_vsp) | + LCDBIT (LCCR_DP_BIT, panel_info.vl_dp) | + LCDBIT (LCCR_BPIX_BIT, panel_info.vl_bpix) | + LCDBIT (LCCR_LBW_BIT, panel_info.vl_lbw) | + LCDBIT (LCCR_SPLT_BIT, panel_info.vl_splt) | + LCDBIT (LCCR_CLOR_BIT, panel_info.vl_clor) | + LCDBIT (LCCR_TFT_BIT, panel_info.vl_tft); + +#if 0 + lccrtmp |= ((SIU_LEVEL5 / 2) << 12); + lccrtmp |= LCCR_EIEN; +#endif + + lcdp->lcd_lccr = lccrtmp; + lcdp->lcd_lcsr = 0xFF; /* Clear pending interrupts */ + + /* Initialize LCD controller bus priorities. + */ +#ifdef CONFIG_RBC823 + immr->im_siu_conf.sc_sdcr = (immr->im_siu_conf.sc_sdcr & ~0x0f) | 1; /* RAID = 01, LAID = 00 */ +#else + immr->im_siu_conf.sc_sdcr &= ~0x0f; /* RAID = LAID = 0 */ + + /* set SHFT/CLOCK division factor 4 + * This needs to be set based upon display type and processor + * speed. The TFT displays run about 20 to 30 MHz. + * I was running 64 MHz processor speed. + * The value for this divider must be chosen so the result is + * an integer of the processor speed (i.e., divide by 3 with + * 64 MHz would be bad). + */ + immr->im_clkrst.car_sccr &= ~0x1F; + immr->im_clkrst.car_sccr |= LCD_DF; /* was 8 */ + +#endif /* CONFIG_RBC823 */ + +#if defined(CONFIG_RBC823) + /* Enable LCD on port D. + */ + immr->im_ioport.iop_pddat &= 0x0300; + immr->im_ioport.iop_pdpar |= 0x1CFF; + immr->im_ioport.iop_pddir |= 0x1CFF; + + /* Configure LCD_ON, VEE_ON, CCFL_ON on port B. + */ + immr->im_cpm.cp_pbdat &= ~0x00005001; + immr->im_cpm.cp_pbpar &= ~0x00005001; + immr->im_cpm.cp_pbdir |= 0x00005001; +#elif !defined(CONFIG_EDT32F10) + /* Enable LCD on port D. + */ + immr->im_ioport.iop_pdpar |= 0x1FFF; + immr->im_ioport.iop_pddir |= 0x1FFF; + + /* Enable LCD_A/B/C on port B. + */ + immr->im_cpm.cp_pbpar |= 0x00005001; + immr->im_cpm.cp_pbdir |= 0x00005001; +#else + /* Enable LCD on port D. + */ + immr->im_ioport.iop_pdpar |= 0x1DFF; + immr->im_ioport.iop_pdpar &= ~0x0200; + immr->im_ioport.iop_pddir |= 0x1FFF; + immr->im_ioport.iop_pddat |= 0x0200; +#endif + + /* Load the physical address of the linear frame buffer + * into the LCD controller. + * BIG NOTE: This has to be modified to load A and B depending + * upon the split mode of the LCD. + */ + lcdp->lcd_lcfaa = (ulong)lcdbase; + lcdp->lcd_lcfba = (ulong)lcdbase; + + /* MORE HACKS...This must be updated according to 823 manual + * for different panels. + * Udi Finkelstein - done - see below: + * Note: You better not try unsupported combinations such as + * 4-bit wide passive dual scan LCD at 4/8 Bit color. + */ + lchcr_hpc_tmp = + (panel_info.vl_col * + (panel_info.vl_tft ? 8 : + (((2 - panel_info.vl_lbw) << /* 4 bit=2, 8-bit = 1 */ + /* use << to mult by: single scan = 1, dual scan = 2 */ + panel_info.vl_splt) * + (panel_info.vl_bpix | 1)))) >> 3; /* 2/4 BPP = 1, 8/16 BPP = 3 */ + + lcdp->lcd_lchcr = LCHCR_BO | + LCDBIT (LCHCR_AT_BIT, 4) | + LCDBIT (LCHCR_HPC_BIT, lchcr_hpc_tmp) | + panel_info.vl_wbl; + + lcdp->lcd_lcvcr = LCDBIT (LCVCR_VPW_BIT, panel_info.vl_vpw) | + LCDBIT (LCVCR_LCD_AC_BIT, panel_info.vl_lcdac) | + LCDBIT (LCVCR_VPC_BIT, panel_info.vl_row) | + panel_info.vl_wbf; + +} + +/*----------------------------------------------------------------------*/ + +#if LCD_BPP == LCD_COLOR8 +void +lcd_setcolreg (ushort regno, ushort red, ushort green, ushort blue) +{ + volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; + volatile cpm8xx_t *cp = &(immr->im_cpm); + unsigned short colreg, *cmap_ptr; + + cmap_ptr = (unsigned short *)&cp->lcd_cmap[regno * 2]; + + colreg = ((red & 0x0F) << 8) | + ((green & 0x0F) << 4) | + (blue & 0x0F) ; +#ifdef CONFIG_SYS_INVERT_COLORS + colreg ^= 0x0FFF; +#endif + *cmap_ptr = colreg; + + debug ("setcolreg: reg %2d @ %p: R=%02X G=%02X B=%02X => %02X%02X\n", + regno, &(cp->lcd_cmap[regno * 2]), + red, green, blue, + cp->lcd_cmap[ regno * 2 ], cp->lcd_cmap[(regno * 2) + 1]); +} +#endif /* LCD_COLOR8 */ + +/*----------------------------------------------------------------------*/ + +#if LCD_BPP == LCD_MONOCHROME +static +void lcd_initcolregs (void) +{ + volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; + volatile cpm8xx_t *cp = &(immr->im_cpm); + ushort regno; + + for (regno = 0; regno < 16; regno++) { + cp->lcd_cmap[regno * 2] = 0; + cp->lcd_cmap[(regno * 2) + 1] = regno & 0x0f; + } +} +#endif + +/*----------------------------------------------------------------------*/ + +void lcd_enable (void) +{ + volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; + volatile lcd823_t *lcdp = &immr->im_lcd; + + /* Enable the LCD panel */ +#ifndef CONFIG_RBC823 + immr->im_siu_conf.sc_sdcr |= (1 << (31 - 25)); /* LAM = 1 */ +#endif + lcdp->lcd_lccr |= LCCR_PON; + +#ifdef CONFIG_V37 + /* Turn on display backlight */ + immr->im_cpm.cp_pbpar |= 0x00008000; + immr->im_cpm.cp_pbdir |= 0x00008000; +#elif defined(CONFIG_RBC823) + /* Turn on display backlight */ + immr->im_cpm.cp_pbdat |= 0x00004000; +#endif + +#if defined(CONFIG_LWMON) + { uchar c = pic_read (0x60); +#if defined(CONFIG_LCD) && defined(CONFIG_LWMON) && (CONFIG_POST & CONFIG_SYS_POST_SYSMON) + /* Enable LCD later in sysmon test, only if temperature is OK */ +#else + c |= 0x07; /* Power on CCFL, Enable CCFL, Chip Enable LCD */ +#endif + pic_write (0x60, c); + } +#endif /* CONFIG_LWMON */ + +#if defined(CONFIG_R360MPI) + { + extern void r360_i2c_lcd_write (uchar data0, uchar data1); + unsigned long bgi, ctr; + char *p; + + if ((p = getenv("lcdbgi")) != NULL) { + bgi = simple_strtoul (p, 0, 10) & 0xFFF; + } else { + bgi = 0xFFF; + } + + if ((p = getenv("lcdctr")) != NULL) { + ctr = simple_strtoul (p, 0, 10) & 0xFFF; + } else { + ctr=0x7FF; + } + + r360_i2c_lcd_write(0x10, 0x01); + r360_i2c_lcd_write(0x20, 0x01); + r360_i2c_lcd_write(0x30 | ((bgi>>8) & 0xF), bgi & 0xFF); + r360_i2c_lcd_write(0x40 | ((ctr>>8) & 0xF), ctr & 0xFF); + } +#endif /* CONFIG_R360MPI */ +#ifdef CONFIG_RBC823 + udelay(200000); /* wait 200ms */ + /* Turn VEE_ON first */ + immr->im_cpm.cp_pbdat |= 0x00000001; + udelay(200000); /* wait 200ms */ + /* Now turn on LCD_ON */ + immr->im_cpm.cp_pbdat |= 0x00001000; +#endif +#ifdef CONFIG_RRVISION + debug ("PC4->Output(1): enable LVDS\n"); + debug ("PC5->Output(0): disable PAL clock\n"); + immr->im_ioport.iop_pddir |= 0x1000; + immr->im_ioport.iop_pcpar &= ~(0x0C00); + immr->im_ioport.iop_pcdir |= 0x0C00 ; + immr->im_ioport.iop_pcdat |= 0x0800 ; + immr->im_ioport.iop_pcdat &= ~(0x0400); + debug ("PDPAR=0x%04X PDDIR=0x%04X PDDAT=0x%04X\n", + immr->im_ioport.iop_pdpar, + immr->im_ioport.iop_pddir, + immr->im_ioport.iop_pddat); + debug ("PCPAR=0x%04X PCDIR=0x%04X PCDAT=0x%04X\n", + immr->im_ioport.iop_pcpar, + immr->im_ioport.iop_pcdir, + immr->im_ioport.iop_pcdat); +#endif +} + +/*----------------------------------------------------------------------*/ + +#if defined (CONFIG_RBC823) +void lcd_disable (void) +{ + volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; + volatile lcd823_t *lcdp = &immr->im_lcd; + +#if defined(CONFIG_LWMON) + { uchar c = pic_read (0x60); + c &= ~0x07; /* Power off CCFL, Disable CCFL, Chip Disable LCD */ + pic_write (0x60, c); + } +#elif defined(CONFIG_R360MPI) + { + extern void r360_i2c_lcd_write (uchar data0, uchar data1); + + r360_i2c_lcd_write(0x10, 0x00); + r360_i2c_lcd_write(0x20, 0x00); + r360_i2c_lcd_write(0x30, 0x00); + r360_i2c_lcd_write(0x40, 0x00); + } +#endif /* CONFIG_LWMON */ + /* Disable the LCD panel */ + lcdp->lcd_lccr &= ~LCCR_PON; +#ifdef CONFIG_RBC823 + /* Turn off display backlight, VEE and LCD_ON */ + immr->im_cpm.cp_pbdat &= ~0x00005001; +#else + immr->im_siu_conf.sc_sdcr &= ~(1 << (31 - 25)); /* LAM = 0 */ +#endif /* CONFIG_RBC823 */ +} +#endif /* NOT_USED_SO_FAR || CONFIG_RBC823 */ + + +/************************************************************************/ + +#endif /* CONFIG_LCD */ diff --git a/drivers/video/pxa_lcd.c b/drivers/video/pxa_lcd.c new file mode 100644 index 0000000..b40ec36 --- /dev/null +++ b/drivers/video/pxa_lcd.c @@ -0,0 +1,609 @@ +/* + * PXA LCD Controller + * + * (C) Copyright 2001-2002 + * Wolfgang Denk, DENX Software Engineering -- wd@denx.de + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/************************************************************************/ +/* ** HEADER FILES */ +/************************************************************************/ + +#include <config.h> +#include <common.h> +#include <version.h> +#include <stdarg.h> +#include <linux/types.h> +#include <stdio_dev.h> +#include <lcd.h> +#include <asm/arch/pxa-regs.h> +#include <asm/io.h> + +/* #define DEBUG */ + +#ifdef CONFIG_LCD + +/*----------------------------------------------------------------------*/ +/* + * Define panel bpp, LCCR0, LCCR3 and panel_info video struct for + * your display. + */ + +#ifdef CONFIG_PXA_VGA +/* LCD outputs connected to a video DAC */ +# define LCD_BPP LCD_COLOR8 + +/* you have to set lccr0 and lccr3 (including pcd) */ +# define REG_LCCR0 0x003008f8 +# define REG_LCCR3 0x0300FF01 + +/* 640x480x16 @ 61 Hz */ +vidinfo_t panel_info = { + .vl_col = 640, + .vl_row = 480, + .vl_width = 640, + .vl_height = 480, + .vl_clkp = CONFIG_SYS_HIGH, + .vl_oep = CONFIG_SYS_HIGH, + .vl_hsp = CONFIG_SYS_HIGH, + .vl_vsp = CONFIG_SYS_HIGH, + .vl_dp = CONFIG_SYS_HIGH, + .vl_bpix = LCD_BPP, + .vl_lbw = 0, + .vl_splt = 0, + .vl_clor = 0, + .vl_tft = 1, + .vl_hpw = 40, + .vl_blw = 56, + .vl_elw = 56, + .vl_vpw = 20, + .vl_bfw = 8, + .vl_efw = 8, +}; +#endif /* CONFIG_PXA_VIDEO */ + +/*----------------------------------------------------------------------*/ +#ifdef CONFIG_SHARP_LM8V31 + +# define LCD_BPP LCD_COLOR8 +# define LCD_INVERT_COLORS /* Needed for colors to be correct, but why? */ + +/* you have to set lccr0 and lccr3 (including pcd) */ +# define REG_LCCR0 0x0030087C +# define REG_LCCR3 0x0340FF08 + +vidinfo_t panel_info = { + .vl_col = 640, + .vl_row = 480, + .vl_width = 157, + .vl_height = 118, + .vl_clkp = CONFIG_SYS_HIGH, + .vl_oep = CONFIG_SYS_HIGH, + .vl_hsp = CONFIG_SYS_HIGH, + .vl_vsp = CONFIG_SYS_HIGH, + .vl_dp = CONFIG_SYS_HIGH, + .vl_bpix = LCD_BPP, + .vl_lbw = 0, + .vl_splt = 1, + .vl_clor = 1, + .vl_tft = 0, + .vl_hpw = 1, + .vl_blw = 3, + .vl_elw = 3, + .vl_vpw = 1, + .vl_bfw = 0, + .vl_efw = 0, +}; +#endif /* CONFIG_SHARP_LM8V31 */ +/*----------------------------------------------------------------------*/ +#ifdef CONFIG_VOIPAC_LCD + +# define LCD_BPP LCD_COLOR8 +# define LCD_INVERT_COLORS + +/* you have to set lccr0 and lccr3 (including pcd) */ +# define REG_LCCR0 0x043008f8 +# define REG_LCCR3 0x0340FF08 + +vidinfo_t panel_info = { + .vl_col = 640, + .vl_row = 480, + .vl_width = 157, + .vl_height = 118, + .vl_clkp = CONFIG_SYS_HIGH, + .vl_oep = CONFIG_SYS_HIGH, + .vl_hsp = CONFIG_SYS_HIGH, + .vl_vsp = CONFIG_SYS_HIGH, + .vl_dp = CONFIG_SYS_HIGH, + .vl_bpix = LCD_BPP, + .vl_lbw = 0, + .vl_splt = 1, + .vl_clor = 1, + .vl_tft = 1, + .vl_hpw = 32, + .vl_blw = 144, + .vl_elw = 32, + .vl_vpw = 2, + .vl_bfw = 13, + .vl_efw = 30, +}; +#endif /* CONFIG_VOIPAC_LCD */ + +/*----------------------------------------------------------------------*/ +#ifdef CONFIG_HITACHI_SX14 +/* Hitachi SX14Q004-ZZA color STN LCD */ +#define LCD_BPP LCD_COLOR8 + +/* you have to set lccr0 and lccr3 (including pcd) */ +#define REG_LCCR0 0x00301079 +#define REG_LCCR3 0x0340FF20 + +vidinfo_t panel_info = { + .vl_col = 320, + .vl_row = 240, + .vl_width = 167, + .vl_height = 109, + .vl_clkp = CONFIG_SYS_HIGH, + .vl_oep = CONFIG_SYS_HIGH, + .vl_hsp = CONFIG_SYS_HIGH, + .vl_vsp = CONFIG_SYS_HIGH, + .vl_dp = CONFIG_SYS_HIGH, + .vl_bpix = LCD_BPP, + .vl_lbw = 1, + .vl_splt = 0, + .vl_clor = 1, + .vl_tft = 0, + .vl_hpw = 1, + .vl_blw = 1, + .vl_elw = 1, + .vl_vpw = 7, + .vl_bfw = 0, + .vl_efw = 0, +}; +#endif /* CONFIG_HITACHI_SX14 */ + +/*----------------------------------------------------------------------*/ +#ifdef CONFIG_LMS283GF05 + +# define LCD_BPP LCD_COLOR8 +/*# define LCD_INVERT_COLORS*/ + +/* you have to set lccr0 and lccr3 (including pcd) */ +# define REG_LCCR0 0x043008f8 +# define REG_LCCR3 0x03b00009 + +vidinfo_t panel_info = { + .vl_col = 240, + .vl_row = 320, + .vl_width = 240, + .vl_height = 320, + .vl_clkp = CONFIG_SYS_HIGH, + .vl_oep = CONFIG_SYS_LOW, + .vl_hsp = CONFIG_SYS_LOW, + .vl_vsp = CONFIG_SYS_LOW, + .vl_dp = CONFIG_SYS_HIGH, + .vl_bpix = LCD_BPP, + .vl_lbw = 0, + .vl_splt = 1, + .vl_clor = 1, + .vl_tft = 1, + .vl_hpw = 4, + .vl_blw = 4, + .vl_elw = 8, + .vl_vpw = 4, + .vl_bfw = 4, + .vl_efw = 8, +}; +#endif /* CONFIG_LMS283GF05 */ + +/*----------------------------------------------------------------------*/ + +#ifdef CONFIG_ACX517AKN + +# define LCD_BPP LCD_COLOR8 + +/* you have to set lccr0 and lccr3 (including pcd) */ +# define REG_LCCR0 0x003008f9 +# define REG_LCCR3 0x03700006 + +vidinfo_t panel_info = { + .vl_col = 320, + .vl_row = 320, + .vl_width = 320, + .vl_height = 320, + .vl_clkp = CONFIG_SYS_HIGH, + .vl_oep = CONFIG_SYS_LOW, + .vl_hsp = CONFIG_SYS_LOW, + .vl_vsp = CONFIG_SYS_LOW, + .vl_dp = CONFIG_SYS_HIGH, + .vl_bpix = LCD_BPP, + .vl_lbw = 0, + .vl_splt = 1, + .vl_clor = 1, + .vl_tft = 1, + .vl_hpw = 0x04, + .vl_blw = 0x1c, + .vl_elw = 0x08, + .vl_vpw = 0x01, + .vl_bfw = 0x07, + .vl_efw = 0x08, +}; +#endif /* CONFIG_ACX517AKN */ + +/*----------------------------------------------------------------------*/ + +#ifdef CONFIG_LQ038J7DH53 + +# define LCD_BPP LCD_COLOR8 + +/* you have to set lccr0 and lccr3 (including pcd) */ +# define REG_LCCR0 0x003008f9 +# define REG_LCCR3 0x03700004 + +vidinfo_t panel_info = { + .vl_col = 320, + .vl_row = 480, + .vl_width = 320, + .vl_height = 480, + .vl_clkp = CONFIG_SYS_HIGH, + .vl_oep = CONFIG_SYS_LOW, + .vl_hsp = CONFIG_SYS_LOW, + .vl_vsp = CONFIG_SYS_LOW, + .vl_dp = CONFIG_SYS_HIGH, + .vl_bpix = LCD_BPP, + .vl_lbw = 0, + .vl_splt = 1, + .vl_clor = 1, + .vl_tft = 1, + .vl_hpw = 0x04, + .vl_blw = 0x20, + .vl_elw = 0x01, + .vl_vpw = 0x01, + .vl_bfw = 0x04, + .vl_efw = 0x01, +}; +#endif /* CONFIG_ACX517AKN */ + +/*----------------------------------------------------------------------*/ + +#ifdef CONFIG_LITTLETON_LCD +# define LCD_BPP LCD_COLOR8 + +/* you have to set lccr0 and lccr3 (including pcd) */ +# define REG_LCCR0 0x003008f8 +# define REG_LCCR3 0x0300FF04 + +vidinfo_t panel_info = { + .vl_col = 480, + .vl_row = 640, + .vl_width = 480, + .vl_height = 640, + .vl_clkp = CONFIG_SYS_HIGH, + .vl_oep = CONFIG_SYS_HIGH, + .vl_hsp = CONFIG_SYS_HIGH, + .vl_vsp = CONFIG_SYS_HIGH, + .vl_dp = CONFIG_SYS_HIGH, + .vl_bpix = LCD_BPP, + .vl_lbw = 0, + .vl_splt = 0, + .vl_clor = 0, + .vl_tft = 1, + .vl_hpw = 9, + .vl_blw = 8, + .vl_elw = 24, + .vl_vpw = 2, + .vl_bfw = 2, + .vl_efw = 4, +}; +#endif /* CONFIG_LITTLETON_LCD */ + +/*----------------------------------------------------------------------*/ + +static int pxafb_init_mem (void *lcdbase, vidinfo_t *vid); +static void pxafb_setup_gpio (vidinfo_t *vid); +static void pxafb_enable_controller (vidinfo_t *vid); +static int pxafb_init (vidinfo_t *vid); + +/************************************************************************/ +/* --------------- PXA chipset specific functions ------------------- */ +/************************************************************************/ + +void lcd_ctrl_init (void *lcdbase) +{ + pxafb_init_mem(lcdbase, &panel_info); + pxafb_init(&panel_info); + pxafb_setup_gpio(&panel_info); + pxafb_enable_controller(&panel_info); +} + +/*----------------------------------------------------------------------*/ +#if LCD_BPP == LCD_COLOR8 +void +lcd_setcolreg (ushort regno, ushort red, ushort green, ushort blue) +{ + struct pxafb_info *fbi = &panel_info.pxa; + unsigned short *palette = (unsigned short *)fbi->palette; + u_int val; + + if (regno < fbi->palette_size) { + val = ((red << 8) & 0xf800); + val |= ((green << 4) & 0x07e0); + val |= (blue & 0x001f); + +#ifdef LCD_INVERT_COLORS + palette[regno] = ~val; +#else + palette[regno] = val; +#endif + } + + debug ("setcolreg: reg %2d @ %p: R=%02X G=%02X B=%02X => %04X\n", + regno, &palette[regno], + red, green, blue, + palette[regno]); +} +#endif /* LCD_COLOR8 */ + +/*----------------------------------------------------------------------*/ +#if LCD_BPP == LCD_MONOCHROME +void lcd_initcolregs (void) +{ + struct pxafb_info *fbi = &panel_info.pxa; + cmap = (ushort *)fbi->palette; + ushort regno; + + for (regno = 0; regno < 16; regno++) { + cmap[regno * 2] = 0; + cmap[(regno * 2) + 1] = regno & 0x0f; + } +} +#endif /* LCD_MONOCHROME */ + +/*----------------------------------------------------------------------*/ +void lcd_enable (void) +{ +} + +/************************************************************************/ +/* ** PXA255 specific routines */ +/************************************************************************/ + +/* + * Calculate fb size for VIDEOLFB_ATAG. Size returned contains fb, + * descriptors and palette areas. + */ +ulong calc_fbsize (void) +{ + ulong size; + int line_length = (panel_info.vl_col * NBITS (panel_info.vl_bpix)) / 8; + + size = line_length * panel_info.vl_row; + size += PAGE_SIZE; + + return size; +} + +static int pxafb_init_mem (void *lcdbase, vidinfo_t *vid) +{ + u_long palette_mem_size; + struct pxafb_info *fbi = &vid->pxa; + int fb_size = vid->vl_row * (vid->vl_col * NBITS (vid->vl_bpix)) / 8; + + fbi->screen = (u_long)lcdbase; + + fbi->palette_size = NBITS(vid->vl_bpix) == 8 ? 256 : 16; + palette_mem_size = fbi->palette_size * sizeof(u16); + + debug("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size); + /* locate palette and descs at end of page following fb */ + fbi->palette = (u_long)lcdbase + fb_size + PAGE_SIZE - palette_mem_size; + + return 0; +} +#ifdef CONFIG_CPU_MONAHANS +static inline void pxafb_setup_gpio (vidinfo_t *vid) {} +#else +static void pxafb_setup_gpio (vidinfo_t *vid) +{ + u_long lccr0; + + /* + * setup is based on type of panel supported + */ + + lccr0 = vid->pxa.reg_lccr0; + + /* 4 bit interface */ + if ((lccr0 & LCCR0_CMS) && (lccr0 & LCCR0_SDS) && !(lccr0 & LCCR0_DPD)) + { + debug("Setting GPIO for 4 bit data\n"); + /* bits 58-61 */ + writel(readl(GPDR1) | (0xf << 26), GPDR1); + writel((readl(GAFR1_U) & ~(0xff << 20)) | (0xaa << 20), + GAFR1_U); + + /* bits 74-77 */ + writel(readl(GPDR2) | (0xf << 10), GPDR2); + writel((readl(GAFR2_L) & ~(0xff << 20)) | (0xaa << 20), + GAFR2_L); + } + + /* 8 bit interface */ + else if (((lccr0 & LCCR0_CMS) && ((lccr0 & LCCR0_SDS) || (lccr0 & LCCR0_DPD))) || + (!(lccr0 & LCCR0_CMS) && !(lccr0 & LCCR0_PAS) && !(lccr0 & LCCR0_SDS))) + { + debug("Setting GPIO for 8 bit data\n"); + /* bits 58-65 */ + writel(readl(GPDR1) | (0x3f << 26), GPDR1); + writel(readl(GPDR2) | (0x3), GPDR2); + + writel((readl(GAFR1_U) & ~(0xfff << 20)) | (0xaaa << 20), + GAFR1_U); + writel((readl(GAFR2_L) & ~0xf) | (0xa), GAFR2_L); + + /* bits 74-77 */ + writel(readl(GPDR2) | (0xf << 10), GPDR2); + writel((readl(GAFR2_L) & ~(0xff << 20)) | (0xaa << 20), + GAFR2_L); + } + + /* 16 bit interface */ + else if (!(lccr0 & LCCR0_CMS) && ((lccr0 & LCCR0_SDS) || (lccr0 & LCCR0_PAS))) + { + debug("Setting GPIO for 16 bit data\n"); + /* bits 58-77 */ + writel(readl(GPDR1) | (0x3f << 26), GPDR1); + writel(readl(GPDR2) | 0x00003fff, GPDR2); + + writel((readl(GAFR1_U) & ~(0xfff << 20)) | (0xaaa << 20), + GAFR1_U); + writel((readl(GAFR2_L) & 0xf0000000) | 0x0aaaaaaa, GAFR2_L); + } + else + { + printf("pxafb_setup_gpio: unable to determine bits per pixel\n"); + } +} +#endif + +static void pxafb_enable_controller (vidinfo_t *vid) +{ + debug("Enabling LCD controller\n"); + + /* Sequence from 11.7.10 */ + writel(vid->pxa.reg_lccr3, LCCR3); + writel(vid->pxa.reg_lccr2, LCCR2); + writel(vid->pxa.reg_lccr1, LCCR1); + writel(vid->pxa.reg_lccr0 & ~LCCR0_ENB, LCCR0); + writel(vid->pxa.fdadr0, FDADR0); + writel(vid->pxa.fdadr1, FDADR1); + writel(readl(LCCR0) | LCCR0_ENB, LCCR0); + +#ifdef CONFIG_CPU_MONAHANS + writel(readl(CKENA) | CKENA_1_LCD, CKENA); +#else + writel(readl(CKEN) | CKEN16_LCD, CKEN); +#endif + + debug("FDADR0 = 0x%08x\n", readl(FDADR0)); + debug("FDADR1 = 0x%08x\n", readl(FDADR1)); + debug("LCCR0 = 0x%08x\n", readl(LCCR0)); + debug("LCCR1 = 0x%08x\n", readl(LCCR1)); + debug("LCCR2 = 0x%08x\n", readl(LCCR2)); + debug("LCCR3 = 0x%08x\n", readl(LCCR3)); +} + +static int pxafb_init (vidinfo_t *vid) +{ + struct pxafb_info *fbi = &vid->pxa; + + debug("Configuring PXA LCD\n"); + + fbi->reg_lccr0 = REG_LCCR0; + fbi->reg_lccr3 = REG_LCCR3; + + debug("vid: vl_col=%d hslen=%d lm=%d rm=%d\n", + vid->vl_col, vid->vl_hpw, + vid->vl_blw, vid->vl_elw); + debug("vid: vl_row=%d vslen=%d um=%d bm=%d\n", + vid->vl_row, vid->vl_vpw, + vid->vl_bfw, vid->vl_efw); + + fbi->reg_lccr1 = + LCCR1_DisWdth(vid->vl_col) + + LCCR1_HorSnchWdth(vid->vl_hpw) + + LCCR1_BegLnDel(vid->vl_blw) + + LCCR1_EndLnDel(vid->vl_elw); + + fbi->reg_lccr2 = + LCCR2_DisHght(vid->vl_row) + + LCCR2_VrtSnchWdth(vid->vl_vpw) + + LCCR2_BegFrmDel(vid->vl_bfw) + + LCCR2_EndFrmDel(vid->vl_efw); + + fbi->reg_lccr3 = REG_LCCR3 & ~(LCCR3_HSP | LCCR3_VSP); + fbi->reg_lccr3 |= (vid->vl_hsp ? LCCR3_HorSnchL : LCCR3_HorSnchH) + | (vid->vl_vsp ? LCCR3_VrtSnchL : LCCR3_VrtSnchH); + + + /* setup dma descriptors */ + fbi->dmadesc_fblow = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette - 3*16); + fbi->dmadesc_fbhigh = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette - 2*16); + fbi->dmadesc_palette = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette - 1*16); + + #define BYTES_PER_PANEL ((fbi->reg_lccr0 & LCCR0_SDS) ? \ + (vid->vl_col * vid->vl_row * NBITS(vid->vl_bpix) / 8 / 2) : \ + (vid->vl_col * vid->vl_row * NBITS(vid->vl_bpix) / 8)) + + /* populate descriptors */ + fbi->dmadesc_fblow->fdadr = (u_long)fbi->dmadesc_fblow; + fbi->dmadesc_fblow->fsadr = fbi->screen + BYTES_PER_PANEL; + fbi->dmadesc_fblow->fidr = 0; + fbi->dmadesc_fblow->ldcmd = BYTES_PER_PANEL; + + fbi->fdadr1 = (u_long)fbi->dmadesc_fblow; /* only used in dual-panel mode */ + + fbi->dmadesc_fbhigh->fsadr = fbi->screen; + fbi->dmadesc_fbhigh->fidr = 0; + fbi->dmadesc_fbhigh->ldcmd = BYTES_PER_PANEL; + + fbi->dmadesc_palette->fsadr = fbi->palette; + fbi->dmadesc_palette->fidr = 0; + fbi->dmadesc_palette->ldcmd = (fbi->palette_size * 2) | LDCMD_PAL; + + if( NBITS(vid->vl_bpix) < 12) + { + /* assume any mode with <12 bpp is palette driven */ + fbi->dmadesc_palette->fdadr = (u_long)fbi->dmadesc_fbhigh; + fbi->dmadesc_fbhigh->fdadr = (u_long)fbi->dmadesc_palette; + /* flips back and forth between pal and fbhigh */ + fbi->fdadr0 = (u_long)fbi->dmadesc_palette; + } + else + { + /* palette shouldn't be loaded in true-color mode */ + fbi->dmadesc_fbhigh->fdadr = (u_long)fbi->dmadesc_fbhigh; + fbi->fdadr0 = (u_long)fbi->dmadesc_fbhigh; /* no pal just fbhigh */ + } + + debug("fbi->dmadesc_fblow = 0x%lx\n", (u_long)fbi->dmadesc_fblow); + debug("fbi->dmadesc_fbhigh = 0x%lx\n", (u_long)fbi->dmadesc_fbhigh); + debug("fbi->dmadesc_palette = 0x%lx\n", (u_long)fbi->dmadesc_palette); + + debug("fbi->dmadesc_fblow->fdadr = 0x%lx\n", fbi->dmadesc_fblow->fdadr); + debug("fbi->dmadesc_fbhigh->fdadr = 0x%lx\n", fbi->dmadesc_fbhigh->fdadr); + debug("fbi->dmadesc_palette->fdadr = 0x%lx\n", fbi->dmadesc_palette->fdadr); + + debug("fbi->dmadesc_fblow->fsadr = 0x%lx\n", fbi->dmadesc_fblow->fsadr); + debug("fbi->dmadesc_fbhigh->fsadr = 0x%lx\n", fbi->dmadesc_fbhigh->fsadr); + debug("fbi->dmadesc_palette->fsadr = 0x%lx\n", fbi->dmadesc_palette->fsadr); + + debug("fbi->dmadesc_fblow->ldcmd = 0x%lx\n", fbi->dmadesc_fblow->ldcmd); + debug("fbi->dmadesc_fbhigh->ldcmd = 0x%lx\n", fbi->dmadesc_fbhigh->ldcmd); + debug("fbi->dmadesc_palette->ldcmd = 0x%lx\n", fbi->dmadesc_palette->ldcmd); + + return 0; +} + +/************************************************************************/ +/************************************************************************/ + +#endif /* CONFIG_LCD */ diff --git a/drivers/video/tegra.c b/drivers/video/tegra.c index afcb008..8d53395 100644 --- a/drivers/video/tegra.c +++ b/drivers/video/tegra.c @@ -60,77 +60,15 @@ enum { LCD_MAX_LOG2_BPP = 4, /* 2^4 = 16 bpp */ }; -int lcd_line_length; -int lcd_color_fg; -int lcd_color_bg; - -void *lcd_base; /* Start of framebuffer memory */ -void *lcd_console_address; /* Start of console buffer */ - -short console_col; -short console_row; - vidinfo_t panel_info = { /* Insert a value here so that we don't end up in the BSS */ .vl_col = -1, }; -char lcd_cursor_enabled; - -ushort lcd_cursor_width; -ushort lcd_cursor_height; - #ifndef CONFIG_OF_CONTROL #error "You must enable CONFIG_OF_CONTROL to get Tegra LCD support" #endif -void lcd_cursor_size(ushort width, ushort height) -{ - lcd_cursor_width = width; - lcd_cursor_height = height; -} - -void lcd_toggle_cursor(void) -{ - ushort x, y; - uchar *dest; - ushort row; - - x = console_col * lcd_cursor_width; - y = console_row * lcd_cursor_height; - dest = (uchar *)(lcd_base + y * lcd_line_length + x * (1 << LCD_BPP) / - 8); - - for (row = 0; row < lcd_cursor_height; ++row, dest += lcd_line_length) { - ushort *d = (ushort *)dest; - ushort color; - int i; - - for (i = 0; i < lcd_cursor_width; ++i) { - color = *d; - color ^= lcd_color_fg; - *d = color; - ++d; - } - } -} - -void lcd_cursor_on(void) -{ - lcd_cursor_enabled = 1; - lcd_toggle_cursor(); -} -void lcd_cursor_off(void) -{ - lcd_cursor_enabled = 0; - lcd_toggle_cursor(); -} - -char lcd_is_cursor_enabled(void) -{ - return lcd_cursor_enabled; -} - static void update_panel_size(struct fdt_disp_config *config) { panel_info.vl_col = config->width; @@ -150,8 +88,6 @@ void lcd_ctrl_init(void *lcdbase) assert(disp_config); - lcd_base = (void *)disp_config->frame_buffer; - /* Make sure that we can acommodate the selected LCD */ assert(disp_config->width <= LCD_MAX_WIDTH); assert(disp_config->height <= LCD_MAX_HEIGHT); @@ -172,7 +108,7 @@ void lcd_ctrl_init(void *lcdbase) /* Enable flushing after LCD writes if requested */ lcd_set_flush_dcache(config.cache_type & FDT_LCD_CACHE_FLUSH); - debug("LCD frame buffer at %p\n", lcd_base); + debug("LCD frame buffer at %08X\n", disp_config->frame_buffer); } ulong calc_fbsize(void) |