From f59e69cbd38ff297a07687ba28437c257cd5757c Mon Sep 17 00:00:00 2001 From: Aneesh Bansal Date: Thu, 29 Oct 2015 22:58:03 +0530 Subject: crypto/fsl: SEC driver cleanup for 64 bit and endianness The SEC driver code has been cleaned up to work for 64 bit physical addresses and systems where endianess of SEC block is different from the Core. Changes: 1. Descriptor created on Core is modified as per SEC block endianness before the job is submitted. 2. The read/write of physical addresses to Job Rings will be depend on endianness of SEC block as 32 bit low and high part of the 64 bit address will vary. 3. The 32 bit low and high part of the 64 bit address in descriptor will vary depending on endianness of SEC. Signed-off-by: Aneesh Bansal Reviewed-by: York Sun --- drivers/crypto/fsl/desc_constr.h | 26 ++++++++++++ drivers/crypto/fsl/fsl_hash.c | 8 ++-- drivers/crypto/fsl/jr.c | 86 ++++++++++++++++++++++++++++++++++------ drivers/crypto/fsl/jr.h | 7 ++-- 4 files changed, 107 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/fsl/desc_constr.h b/drivers/crypto/fsl/desc_constr.h index f9cae91..2559ccd 100644 --- a/drivers/crypto/fsl/desc_constr.h +++ b/drivers/crypto/fsl/desc_constr.h @@ -36,6 +36,23 @@ LDST_SRCDST_WORD_DECOCTRL | \ (LDOFF_ENABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT)) +#ifdef CONFIG_PHYS_64BIT +union ptr_addr_t { + u64 m_whole; + struct { +#ifdef CONFIG_SYS_FSL_SEC_LE + u32 low; + u32 high; +#elif defined(CONFIG_SYS_FSL_SEC_BE) + u32 high; + u32 low; +#else +#error Neither CONFIG_SYS_FSL_SEC_LE nor CONFIG_SYS_FSL_SEC_BE is defined +#endif + } m_halfs; +}; +#endif + static inline int desc_len(u32 *desc) { return *desc & HDR_DESCLEN_MASK; @@ -65,7 +82,16 @@ static inline void append_ptr(u32 *desc, dma_addr_t ptr) { dma_addr_t *offset = (dma_addr_t *)desc_end(desc); +#ifdef CONFIG_PHYS_64BIT + /* The Position of low and high part of 64 bit address + * will depend on the endianness of CAAM Block */ + union ptr_addr_t ptr_addr; + ptr_addr.m_halfs.high = (u32)(ptr >> 32); + ptr_addr.m_halfs.low = (u32)ptr; + *offset = ptr_addr.m_whole; +#else *offset = ptr; +#endif (*desc) += CAAM_PTR_SZ / CAAM_CMD_SZ; } diff --git a/drivers/crypto/fsl/fsl_hash.c b/drivers/crypto/fsl/fsl_hash.c index c298404..887e88c 100644 --- a/drivers/crypto/fsl/fsl_hash.c +++ b/drivers/crypto/fsl/fsl_hash.c @@ -84,7 +84,7 @@ static int caam_hash_update(void *hash_ctx, const void *buf, enum caam_hash_algos caam_algo) { uint32_t final = 0; - dma_addr_t addr = virt_to_phys((void *)buf); + phys_addr_t addr = virt_to_phys((void *)buf); struct sha_ctx *ctx = hash_ctx; if (ctx->sg_num >= MAX_SG_32) { @@ -93,11 +93,11 @@ static int caam_hash_update(void *hash_ctx, const void *buf, } #ifdef CONFIG_PHYS_64BIT - ctx->sg_tbl[ctx->sg_num].addr_hi = addr >> 32; + sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, (uint32_t)(addr >> 32)); #else - ctx->sg_tbl[ctx->sg_num].addr_hi = 0x0; + sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, 0x0); #endif - ctx->sg_tbl[ctx->sg_num].addr_lo = addr; + sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_lo, (uint32_t)addr); sec_out32(&ctx->sg_tbl[ctx->sg_num].len_flag, (size & SG_ENTRY_LENGTH_MASK)); diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c index 17392c9..f63eacb 100644 --- a/drivers/crypto/fsl/jr.c +++ b/drivers/crypto/fsl/jr.c @@ -11,6 +11,7 @@ #include "fsl_sec.h" #include "jr.h" #include "jobdesc.h" +#include "desc_constr.h" #define CIRC_CNT(head, tail, size) (((head) - (tail)) & (size - 1)) #define CIRC_SPACE(head, tail, size) CIRC_CNT((tail), (head) + 1, (size)) @@ -154,19 +155,35 @@ static int jr_hw_reset(void) /* -1 --- error, can't enqueue -- no space available */ static int jr_enqueue(uint32_t *desc_addr, - void (*callback)(uint32_t desc, uint32_t status, void *arg), + void (*callback)(uint32_t status, void *arg), void *arg) { struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR; int head = jr.head; - dma_addr_t desc_phys_addr = virt_to_phys(desc_addr); + uint32_t desc_word; + int length = desc_len(desc_addr); + int i; +#ifdef CONFIG_PHYS_64BIT + uint32_t *addr_hi, *addr_lo; +#endif + + /* The descriptor must be submitted to SEC block as per endianness + * of the SEC Block. + * So, if the endianness of Core and SEC block is different, each word + * of the descriptor will be byte-swapped. + */ + for (i = 0; i < length; i++) { + desc_word = desc_addr[i]; + sec_out32((uint32_t *)&desc_addr[i], desc_word); + } + + phys_addr_t desc_phys_addr = virt_to_phys(desc_addr); if (sec_in32(®s->irsa) == 0 || CIRC_SPACE(jr.head, jr.tail, jr.size) <= 0) return -1; jr.info[head].desc_phys_addr = desc_phys_addr; - jr.info[head].desc_addr = (uint32_t)desc_addr; jr.info[head].callback = (void *)callback; jr.info[head].arg = arg; jr.info[head].op_done = 0; @@ -177,9 +194,29 @@ static int jr_enqueue(uint32_t *desc_addr, ARCH_DMA_MINALIGN); flush_dcache_range(start, end); - jr.input_ring[head] = desc_phys_addr; +#ifdef CONFIG_PHYS_64BIT + /* Write the 64 bit Descriptor address on Input Ring. + * The 32 bit hign and low part of the address will + * depend on endianness of SEC block. + */ +#ifdef CONFIG_SYS_FSL_SEC_LE + addr_lo = (uint32_t *)(&jr.input_ring[head]); + addr_hi = (uint32_t *)(&jr.input_ring[head]) + 1; +#elif defined(CONFIG_SYS_FSL_SEC_BE) + addr_hi = (uint32_t *)(&jr.input_ring[head]); + addr_lo = (uint32_t *)(&jr.input_ring[head]) + 1; +#endif /* ifdef CONFIG_SYS_FSL_SEC_LE */ + + sec_out32(addr_hi, (uint32_t)(desc_phys_addr >> 32)); + sec_out32(addr_lo, (uint32_t)(desc_phys_addr)); + +#else + /* Write the 32 bit Descriptor address on Input Ring. */ + sec_out32(&jr.input_ring[head], desc_phys_addr); +#endif /* ifdef CONFIG_PHYS_64BIT */ + start = (unsigned long)&jr.input_ring[head] & ~(ARCH_DMA_MINALIGN - 1); - end = ALIGN(start + sizeof(dma_addr_t), ARCH_DMA_MINALIGN); + end = ALIGN(start + sizeof(phys_addr_t), ARCH_DMA_MINALIGN); flush_dcache_range(start, end); jr.head = (head + 1) & (jr.size - 1); @@ -195,8 +232,13 @@ static int jr_dequeue(void) int head = jr.head; int tail = jr.tail; int idx, i, found; - void (*callback)(uint32_t desc, uint32_t status, void *arg); + void (*callback)(uint32_t status, void *arg); void *arg = NULL; +#ifdef CONFIG_PHYS_64BIT + uint32_t *addr_hi, *addr_lo; +#else + uint32_t *addr; +#endif while (sec_in32(®s->orsf) && CIRC_CNT(jr.head, jr.tail, jr.size)) { unsigned long start = (unsigned long)jr.output_ring & @@ -208,14 +250,34 @@ static int jr_dequeue(void) found = 0; - dma_addr_t op_desc = jr.output_ring[jr.tail].desc; - uint32_t status = jr.output_ring[jr.tail].status; - uint32_t desc_virt; + phys_addr_t op_desc; + #ifdef CONFIG_PHYS_64BIT + /* Read the 64 bit Descriptor address from Output Ring. + * The 32 bit hign and low part of the address will + * depend on endianness of SEC block. + */ + #ifdef CONFIG_SYS_FSL_SEC_LE + addr_lo = (uint32_t *)(&jr.output_ring[jr.tail].desc); + addr_hi = (uint32_t *)(&jr.output_ring[jr.tail].desc) + 1; + #elif defined(CONFIG_SYS_FSL_SEC_BE) + addr_hi = (uint32_t *)(&jr.output_ring[jr.tail].desc); + addr_lo = (uint32_t *)(&jr.output_ring[jr.tail].desc) + 1; + #endif /* ifdef CONFIG_SYS_FSL_SEC_LE */ + + op_desc = ((u64)sec_in32(addr_hi) << 32) | + ((u64)sec_in32(addr_lo)); + + #else + /* Read the 32 bit Descriptor address from Output Ring. */ + addr = (uint32_t *)&jr.output_ring[jr.tail].desc; + op_desc = sec_in32(addr); + #endif /* ifdef CONFIG_PHYS_64BIT */ + + uint32_t status = sec_in32(&jr.output_ring[jr.tail].status); for (i = 0; CIRC_CNT(head, tail + i, jr.size) >= 1; i++) { idx = (tail + i) & (jr.size - 1); if (op_desc == jr.info[idx].desc_phys_addr) { - desc_virt = jr.info[idx].desc_addr; found = 1; break; } @@ -244,13 +306,13 @@ static int jr_dequeue(void) sec_out32(®s->orjr, 1); jr.info[idx].op_done = 0; - callback(desc_virt, status, arg); + callback(status, arg); } return 0; } -static void desc_done(uint32_t desc, uint32_t status, void *arg) +static void desc_done(uint32_t status, void *arg) { struct result *x = arg; x->status = status; diff --git a/drivers/crypto/fsl/jr.h b/drivers/crypto/fsl/jr.h index 1526060..5899696 100644 --- a/drivers/crypto/fsl/jr.h +++ b/drivers/crypto/fsl/jr.h @@ -37,14 +37,13 @@ #define JQ_ENQ_ERR -3 struct op_ring { - dma_addr_t desc; + phys_addr_t desc; uint32_t status; } __packed; struct jr_info { - void (*callback)(dma_addr_t desc, uint32_t status, void *arg); - dma_addr_t desc_phys_addr; - uint32_t desc_addr; + void (*callback)(uint32_t status, void *arg); + phys_addr_t desc_phys_addr; uint32_t desc_len; uint32_t op_done; void *arg; -- cgit v1.1 From 7b2edb8b9dd9e9b792f1b2b5c5db4ce57fb1c6f0 Mon Sep 17 00:00:00 2001 From: Prabhakar Kushwaha Date: Wed, 7 Oct 2015 16:29:58 +0530 Subject: driver: net: ldpaa_eth: Set MAC address during interface open Currently ldpaa ethernet driver rely on DPL file to statically configure mac address for the DPNIs. It is not a correct approach. Add support setting MAC address from env variable or Random MAC address. Signed-off-by: Prabhakar Kushwaha Reviewed-by: York Sun --- drivers/net/ldpaa_eth/ldpaa_eth.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c index 4de7586..99acb7a 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.c +++ b/drivers/net/ldpaa_eth/ldpaa_eth.c @@ -220,7 +220,6 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) { struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; struct dpni_queue_attr rx_queue_attr; - uint8_t mac_addr[6]; int err; if (net_dev->state == ETH_STATE_ACTIVE) @@ -240,21 +239,13 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) if (err) goto err_bind; - err = dpni_get_primary_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS, - priv->dpni_handle, mac_addr); + err = dpni_add_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS, + priv->dpni_handle, net_dev->enetaddr); if (err) { - printf("dpni_get_primary_mac_addr() failed\n"); + printf("dpni_add_mac_addr() failed\n"); return err; } - memcpy(net_dev->enetaddr, mac_addr, 0x6); - - /* setup the MAC address */ - if (net_dev->enetaddr[0] & 0x01) { - printf("%s: MacAddress is multcast address\n", __func__); - return 1; - } - #ifdef CONFIG_PHYLIB /* TODO Check this path */ err = phy_startup(priv->phydev); -- cgit v1.1 From 648bde6d70ac94685ed454cb938e44454190f19a Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Mon, 26 Oct 2015 19:47:43 +0800 Subject: net/fm: Fix the endian issue to support both endianness platforms The Frame Manager(FMan) is a big-endian peripheral, so the registers, internal MURAM and BDs, which are allocated in main memory and used to communication between core and FMan, should be accessed in big-endian. The big-endian platforms can access them directly as the code implemented so far, while for the little-endian platforms it need to swap the byte-order. Signed-off-by: Hou Zhiqiang Signed-off-by: Shaohui Xie Signed-off-by: Mingkai Hu Signed-off-by: Gong Qianyu Reviewed-by: York Sun --- drivers/net/fm/eth.c | 70 +++++++++++++++++++++++++++------------------------- drivers/net/fm/fm.c | 11 +++++---- 2 files changed, 43 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/net/fm/eth.c b/drivers/net/fm/eth.c index 6702f5a..368d554 100644 --- a/drivers/net/fm/eth.c +++ b/drivers/net/fm/eth.c @@ -109,7 +109,7 @@ static int tgec_is_fibre(struct eth_device *dev) static u16 muram_readw(u16 *addr) { u32 base = (u32)addr & ~0x3; - u32 val32 = *(u32 *)base; + u32 val32 = in_be32((u32 *)base); int byte_pos; u16 ret; @@ -125,7 +125,7 @@ static u16 muram_readw(u16 *addr) static void muram_writew(u16 *addr, u16 val) { u32 base = (u32)addr & ~0x3; - u32 org32 = *(u32 *)base; + u32 org32 = in_be32((u32 *)base); u32 val32; int byte_pos; @@ -135,7 +135,7 @@ static void muram_writew(u16 *addr, u16 val) else val32 = (org32 & 0x0000ffff) | ((u32)val << 16); - *(u32 *)base = val32; + out_be32((u32 *)base, val32); } static void bmi_rx_port_disable(struct fm_bmi_rx_port *rx_port) @@ -213,10 +213,10 @@ static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth) pram_page_offset = (u32)pram - fm_muram_base(fm_eth->fm_index); /* enable global mode- snooping data buffers and BDs */ - pram->mode = PRAM_MODE_GLOBAL; + out_be32(&pram->mode, PRAM_MODE_GLOBAL); /* init the Rx queue descriptor pionter */ - pram->rxqd_ptr = pram_page_offset + 0x20; + out_be32(&pram->rxqd_ptr, pram_page_offset + 0x20); /* set the max receive buffer length, power of 2 */ muram_writew(&pram->mrblr, MAX_RXBUF_LOG2); @@ -243,10 +243,11 @@ static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth) /* init Rx BDs ring */ rxbd = (struct fm_port_bd *)rx_bd_ring_base; for (i = 0; i < RX_BD_RING_SIZE; i++) { - rxbd->status = RxBD_EMPTY; - rxbd->len = 0; - rxbd->buf_ptr_hi = 0; - rxbd->buf_ptr_lo = (u32)rx_buf_pool + i * MAX_RXBUF_LEN; + muram_writew(&rxbd->status, RxBD_EMPTY); + muram_writew(&rxbd->len, 0); + muram_writew(&rxbd->buf_ptr_hi, 0); + out_be32(&rxbd->buf_ptr_lo, (u32)rx_buf_pool + + i * MAX_RXBUF_LEN); rxbd++; } @@ -254,7 +255,7 @@ static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth) rxqd = &pram->rxqd; muram_writew(&rxqd->gen, 0); muram_writew(&rxqd->bd_ring_base_hi, 0); - rxqd->bd_ring_base_lo = (u32)rx_bd_ring_base; + out_be32(&rxqd->bd_ring_base_lo, (u32)rx_bd_ring_base); muram_writew(&rxqd->bd_ring_size, sizeof(struct fm_port_bd) * RX_BD_RING_SIZE); muram_writew(&rxqd->offset_in, 0); @@ -285,10 +286,10 @@ static int fm_eth_tx_port_parameter_init(struct fm_eth *fm_eth) pram_page_offset = (u32)pram - fm_muram_base(fm_eth->fm_index); /* enable global mode- snooping data buffers and BDs */ - pram->mode = PRAM_MODE_GLOBAL; + out_be32(&pram->mode, PRAM_MODE_GLOBAL); /* init the Tx queue descriptor pionter */ - pram->txqd_ptr = pram_page_offset + 0x40; + out_be32(&pram->txqd_ptr, pram_page_offset + 0x40); /* alloc Tx buffer descriptors from main memory */ tx_bd_ring_base = malloc(sizeof(struct fm_port_bd) @@ -304,16 +305,17 @@ static int fm_eth_tx_port_parameter_init(struct fm_eth *fm_eth) /* init Tx BDs ring */ txbd = (struct fm_port_bd *)tx_bd_ring_base; for (i = 0; i < TX_BD_RING_SIZE; i++) { - txbd->status = TxBD_LAST; - txbd->len = 0; - txbd->buf_ptr_hi = 0; - txbd->buf_ptr_lo = 0; + muram_writew(&txbd->status, TxBD_LAST); + muram_writew(&txbd->len, 0); + muram_writew(&txbd->buf_ptr_hi, 0); + out_be32(&txbd->buf_ptr_lo, 0); + txbd++; } /* set the Tx queue decriptor */ txqd = &pram->txqd; muram_writew(&txqd->bd_ring_base_hi, 0); - txqd->bd_ring_base_lo = (u32)tx_bd_ring_base; + out_be32(&txqd->bd_ring_base_lo, (u32)tx_bd_ring_base); muram_writew(&txqd->bd_ring_size, sizeof(struct fm_port_bd) * TX_BD_RING_SIZE); muram_writew(&txqd->offset_in, 0); @@ -368,7 +370,7 @@ static void fmc_tx_port_graceful_stop_enable(struct fm_eth *fm_eth) pram = fm_eth->tx_pram; /* graceful stop transmission of frames */ - pram->mode |= PRAM_MODE_GRACEFUL_STOP; + setbits_be32(&pram->mode, PRAM_MODE_GRACEFUL_STOP); sync(); } @@ -378,7 +380,7 @@ static void fmc_tx_port_graceful_stop_disable(struct fm_eth *fm_eth) pram = fm_eth->tx_pram; /* re-enable transmission of frames */ - pram->mode &= ~PRAM_MODE_GRACEFUL_STOP; + clrbits_be32(&pram->mode, PRAM_MODE_GRACEFUL_STOP); sync(); } @@ -469,19 +471,20 @@ static int fm_eth_send(struct eth_device *dev, void *buf, int len) txbd = fm_eth->cur_txbd; /* find one empty TxBD */ - for (i = 0; txbd->status & TxBD_READY; i++) { + for (i = 0; muram_readw(&txbd->status) & TxBD_READY; i++) { udelay(100); if (i > 0x1000) { - printf("%s: Tx buffer not ready\n", dev->name); + printf("%s: Tx buffer not ready, txbd->status = 0x%x\n", + dev->name, muram_readw(&txbd->status)); return 0; } } /* setup TxBD */ - txbd->buf_ptr_hi = 0; - txbd->buf_ptr_lo = (u32)buf; - txbd->len = len; + muram_writew(&txbd->buf_ptr_hi, 0); + out_be32(&txbd->buf_ptr_lo, (u32)buf); + muram_writew(&txbd->len, len); sync(); - txbd->status = TxBD_READY | TxBD_LAST; + muram_writew(&txbd->status, TxBD_READY | TxBD_LAST); sync(); /* update TxQD, let RISC to send the packet */ @@ -493,10 +496,11 @@ static int fm_eth_send(struct eth_device *dev, void *buf, int len) sync(); /* wait for buffer to be transmitted */ - for (i = 0; txbd->status & TxBD_READY; i++) { + for (i = 0; muram_readw(&txbd->status) & TxBD_READY; i++) { udelay(100); if (i > 0x10000) { - printf("%s: Tx error\n", dev->name); + printf("%s: Tx error, txbd->status = 0x%x\n", + dev->name, muram_readw(&txbd->status)); return 0; } } @@ -525,12 +529,12 @@ static int fm_eth_recv(struct eth_device *dev) fm_eth = (struct fm_eth *)dev->priv; pram = fm_eth->rx_pram; rxbd = fm_eth->cur_rxbd; - status = rxbd->status; + status = muram_readw(&rxbd->status); while (!(status & RxBD_EMPTY)) { if (!(status & RxBD_ERROR)) { - data = (u8 *)rxbd->buf_ptr_lo; - len = rxbd->len; + data = (u8 *)in_be32(&rxbd->buf_ptr_lo); + len = muram_readw(&rxbd->len); net_process_received_packet(data, len); } else { printf("%s: Rx error\n", dev->name); @@ -538,8 +542,8 @@ static int fm_eth_recv(struct eth_device *dev) } /* clear the RxBDs */ - rxbd->status = RxBD_EMPTY; - rxbd->len = 0; + muram_writew(&rxbd->status, RxBD_EMPTY); + muram_writew(&rxbd->len, 0); sync(); /* advance RxBD */ @@ -548,7 +552,7 @@ static int fm_eth_recv(struct eth_device *dev) if (rxbd >= (rxbd_base + RX_BD_RING_SIZE)) rxbd = rxbd_base; /* read next status */ - status = rxbd->status; + status = muram_readw(&rxbd->status); /* update RxQD */ offset_out = muram_readw(&pram->rxqd.offset_out); diff --git a/drivers/net/fm/fm.c b/drivers/net/fm/fm.c index 400e9dd..eb0eb3d 100644 --- a/drivers/net/fm/fm.c +++ b/drivers/net/fm/fm.c @@ -80,11 +80,11 @@ static void fm_upload_ucode(int fm_idx, struct fm_imem *imem, out_be32(&imem->iadd, IRAM_IADD_AIE); /* write microcode to IRAM */ for (i = 0; i < size / 4; i++) - out_be32(&imem->idata, ucode[i]); + out_be32(&imem->idata, (be32_to_cpu(ucode[i]))); /* verify if the writing is over */ out_be32(&imem->iadd, 0); - while ((in_be32(&imem->idata) != ucode[0]) && --timeout) + while ((in_be32(&imem->idata) != be32_to_cpu(ucode[0])) && --timeout) ; if (!timeout) printf("Fman%u: microcode upload timeout\n", fm_idx + 1); @@ -177,14 +177,15 @@ static int fman_upload_firmware(int fm_idx, const struct qe_microcode *ucode = &firmware->microcode[i]; /* Upload a microcode if it's present */ - if (ucode->code_offset) { + if (be32_to_cpu(ucode->code_offset)) { u32 ucode_size; u32 *code; printf("Fman%u: Uploading microcode version %u.%u.%u\n", fm_idx + 1, ucode->major, ucode->minor, ucode->revision); - code = (void *)firmware + ucode->code_offset; - ucode_size = sizeof(u32) * ucode->count; + code = (void *)firmware + + be32_to_cpu(ucode->code_offset); + ucode_size = sizeof(u32) * be32_to_cpu(ucode->count); fm_upload_ucode(fm_idx, fm_imem, code, ucode_size); } } -- cgit v1.1 From 9fc29db116d147adbee0ad07b0e72a657f961305 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Mon, 26 Oct 2015 19:47:44 +0800 Subject: net/fm: Add support for 64-bit platforms The FMan IM driver is developed for 32-bit platfroms and isn't friendly to 64-bit platforms, so do the minimal refactor: 1. Refine the MURAM management and access. 2. Correct the initialization and operations for QDs and BDs. Signed-off-by: Hou Zhiqiang Signed-off-by: Gong Qianyu Reviewed-by: York Sun --- drivers/net/fm/eth.c | 61 ++++++++++++++++++++++++++++++++++++---------------- drivers/net/fm/fm.c | 20 ++++++++++------- drivers/net/fm/fm.h | 12 +++++------ 3 files changed, 60 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/net/fm/eth.c b/drivers/net/fm/eth.c index 368d554..8ecfd06 100644 --- a/drivers/net/fm/eth.c +++ b/drivers/net/fm/eth.c @@ -108,12 +108,12 @@ static int tgec_is_fibre(struct eth_device *dev) static u16 muram_readw(u16 *addr) { - u32 base = (u32)addr & ~0x3; - u32 val32 = in_be32((u32 *)base); + ulong base = (ulong)addr & ~0x3UL; + u32 val32 = in_be32((void *)base); int byte_pos; u16 ret; - byte_pos = (u32)addr & 0x3; + byte_pos = (ulong)addr & 0x3UL; if (byte_pos) ret = (u16)(val32 & 0x0000ffff); else @@ -124,18 +124,18 @@ static u16 muram_readw(u16 *addr) static void muram_writew(u16 *addr, u16 val) { - u32 base = (u32)addr & ~0x3; - u32 org32 = in_be32((u32 *)base); + ulong base = (ulong)addr & ~0x3UL; + u32 org32 = in_be32((void *)base); u32 val32; int byte_pos; - byte_pos = (u32)addr & 0x3; + byte_pos = (ulong)addr & 0x3UL; if (byte_pos) val32 = (org32 & 0xffff0000) | val; else val32 = (org32 & 0x0000ffff) | ((u32)val << 16); - out_be32((u32 *)base, val32); + out_be32((void *)base, val32); } static void bmi_rx_port_disable(struct fm_bmi_rx_port *rx_port) @@ -199,6 +199,8 @@ static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth) u32 pram_page_offset; void *rx_bd_ring_base; void *rx_buf_pool; + u32 bd_ring_base_lo, bd_ring_base_hi; + u32 buf_lo, buf_hi; struct fm_port_bd *rxbd; struct fm_port_qd *rxqd; struct fm_bmi_rx_port *bmi_rx_port = fm_eth->rx_port; @@ -207,10 +209,15 @@ static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth) /* alloc global parameter ram at MURAM */ pram = (struct fm_port_global_pram *)fm_muram_alloc(fm_eth->fm_index, FM_PRAM_SIZE, FM_PRAM_ALIGN); + if (!pram) { + printf("%s: No muram for Rx global parameter\n", __func__); + return 0; + } + fm_eth->rx_pram = pram; /* parameter page offset to MURAM */ - pram_page_offset = (u32)pram - fm_muram_base(fm_eth->fm_index); + pram_page_offset = (void *)pram - fm_muram_base(fm_eth->fm_index); /* enable global mode- snooping data buffers and BDs */ out_be32(&pram->mode, PRAM_MODE_GLOBAL); @@ -234,6 +241,7 @@ static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth) if (!rx_buf_pool) return 0; memset(rx_buf_pool, 0, MAX_RXBUF_LEN * RX_BD_RING_SIZE); + debug("%s: rx_buf_pool = %p\n", __func__, rx_buf_pool); /* save them to fm_eth */ fm_eth->rx_bd_ring = rx_bd_ring_base; @@ -245,17 +253,22 @@ static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth) for (i = 0; i < RX_BD_RING_SIZE; i++) { muram_writew(&rxbd->status, RxBD_EMPTY); muram_writew(&rxbd->len, 0); - muram_writew(&rxbd->buf_ptr_hi, 0); - out_be32(&rxbd->buf_ptr_lo, (u32)rx_buf_pool + - i * MAX_RXBUF_LEN); + buf_hi = upper_32_bits(virt_to_phys(rx_buf_pool + + i * MAX_RXBUF_LEN)); + buf_lo = lower_32_bits(virt_to_phys(rx_buf_pool + + i * MAX_RXBUF_LEN)); + muram_writew(&rxbd->buf_ptr_hi, (u16)buf_hi); + out_be32(&rxbd->buf_ptr_lo, buf_lo); rxbd++; } /* set the Rx queue descriptor */ rxqd = &pram->rxqd; muram_writew(&rxqd->gen, 0); - muram_writew(&rxqd->bd_ring_base_hi, 0); - out_be32(&rxqd->bd_ring_base_lo, (u32)rx_bd_ring_base); + bd_ring_base_hi = upper_32_bits(virt_to_phys(rx_bd_ring_base)); + bd_ring_base_lo = lower_32_bits(virt_to_phys(rx_bd_ring_base)); + muram_writew(&rxqd->bd_ring_base_hi, (u16)bd_ring_base_hi); + out_be32(&rxqd->bd_ring_base_lo, bd_ring_base_lo); muram_writew(&rxqd->bd_ring_size, sizeof(struct fm_port_bd) * RX_BD_RING_SIZE); muram_writew(&rxqd->offset_in, 0); @@ -272,6 +285,7 @@ static int fm_eth_tx_port_parameter_init(struct fm_eth *fm_eth) struct fm_port_global_pram *pram; u32 pram_page_offset; void *tx_bd_ring_base; + u32 bd_ring_base_lo, bd_ring_base_hi; struct fm_port_bd *txbd; struct fm_port_qd *txqd; struct fm_bmi_tx_port *bmi_tx_port = fm_eth->tx_port; @@ -280,10 +294,14 @@ static int fm_eth_tx_port_parameter_init(struct fm_eth *fm_eth) /* alloc global parameter ram at MURAM */ pram = (struct fm_port_global_pram *)fm_muram_alloc(fm_eth->fm_index, FM_PRAM_SIZE, FM_PRAM_ALIGN); + if (!pram) { + printf("%s: No muram for Tx global parameter\n", __func__); + return 0; + } fm_eth->tx_pram = pram; /* parameter page offset to MURAM */ - pram_page_offset = (u32)pram - fm_muram_base(fm_eth->fm_index); + pram_page_offset = (void *)pram - fm_muram_base(fm_eth->fm_index); /* enable global mode- snooping data buffers and BDs */ out_be32(&pram->mode, PRAM_MODE_GLOBAL); @@ -314,8 +332,10 @@ static int fm_eth_tx_port_parameter_init(struct fm_eth *fm_eth) /* set the Tx queue decriptor */ txqd = &pram->txqd; - muram_writew(&txqd->bd_ring_base_hi, 0); - out_be32(&txqd->bd_ring_base_lo, (u32)tx_bd_ring_base); + bd_ring_base_hi = upper_32_bits(virt_to_phys(tx_bd_ring_base)); + bd_ring_base_lo = lower_32_bits(virt_to_phys(tx_bd_ring_base)); + muram_writew(&txqd->bd_ring_base_hi, (u16)bd_ring_base_hi); + out_be32(&txqd->bd_ring_base_lo, bd_ring_base_lo); muram_writew(&txqd->bd_ring_size, sizeof(struct fm_port_bd) * TX_BD_RING_SIZE); muram_writew(&txqd->offset_in, 0); @@ -480,8 +500,8 @@ static int fm_eth_send(struct eth_device *dev, void *buf, int len) } } /* setup TxBD */ - muram_writew(&txbd->buf_ptr_hi, 0); - out_be32(&txbd->buf_ptr_lo, (u32)buf); + muram_writew(&txbd->buf_ptr_hi, (u16)upper_32_bits(virt_to_phys(buf))); + out_be32(&txbd->buf_ptr_lo, lower_32_bits(virt_to_phys(buf))); muram_writew(&txbd->len, len); sync(); muram_writew(&txbd->status, TxBD_READY | TxBD_LAST); @@ -522,6 +542,7 @@ static int fm_eth_recv(struct eth_device *dev) struct fm_port_global_pram *pram; struct fm_port_bd *rxbd, *rxbd_base; u16 status, len; + u32 buf_lo, buf_hi; u8 *data; u16 offset_out; int ret = 1; @@ -533,7 +554,9 @@ static int fm_eth_recv(struct eth_device *dev) while (!(status & RxBD_EMPTY)) { if (!(status & RxBD_ERROR)) { - data = (u8 *)in_be32(&rxbd->buf_ptr_lo); + buf_hi = muram_readw(&rxbd->buf_ptr_hi); + buf_lo = in_be32(&rxbd->buf_ptr_lo); + data = (u8 *)((ulong)(buf_hi << 16) << 16 | buf_lo); len = muram_readw(&rxbd->len); net_process_received_packet(data, len); } else { diff --git a/drivers/net/fm/fm.c b/drivers/net/fm/fm.c index eb0eb3d..df5db72 100644 --- a/drivers/net/fm/fm.c +++ b/drivers/net/fm/fm.c @@ -22,21 +22,22 @@ struct fm_muram muram[CONFIG_SYS_NUM_FMAN]; -u32 fm_muram_base(int fm_idx) +void *fm_muram_base(int fm_idx) { return muram[fm_idx].base; } -u32 fm_muram_alloc(int fm_idx, u32 size, u32 align) +void *fm_muram_alloc(int fm_idx, size_t size, ulong align) { - u32 ret; - u32 align_mask, off; - u32 save; + void *ret; + ulong align_mask; + size_t off; + void *save; align_mask = align - 1; save = muram[fm_idx].alloc; - off = save & align_mask; + off = (ulong)save & align_mask; if (off != 0) muram[fm_idx].alloc += (align - off); off = size & align_mask; @@ -45,6 +46,7 @@ u32 fm_muram_alloc(int fm_idx, u32 size, u32 align) if ((muram[fm_idx].alloc + size) >= muram[fm_idx].top) { muram[fm_idx].alloc = save; printf("%s: run out of ram.\n", __func__); + return NULL; } ret = muram[fm_idx].alloc; @@ -56,7 +58,7 @@ u32 fm_muram_alloc(int fm_idx, u32 size, u32 align) static void fm_init_muram(int fm_idx, void *reg) { - u32 base = (u32)reg; + void *base = reg; muram[fm_idx].base = base; muram[fm_idx].size = CONFIG_SYS_FM_MURAM_SIZE; @@ -256,7 +258,9 @@ static void fm_init_fpm(struct fm_fpm *fpm) static int fm_init_bmi(int fm_idx, struct fm_bmi_common *bmi) { int blk, i, port_id; - u32 val, offset, base; + u32 val; + size_t offset; + void *base; /* alloc free buffer pool in MURAM */ base = fm_muram_alloc(fm_idx, FM_FREE_POOL_SIZE, FM_FREE_POOL_ALIGN); diff --git a/drivers/net/fm/fm.h b/drivers/net/fm/fm.h index a9691c6..73c525e 100644 --- a/drivers/net/fm/fm.h +++ b/drivers/net/fm/fm.h @@ -26,10 +26,10 @@ #define MIIM_TIMEOUT 0xFFFF struct fm_muram { - u32 base; - u32 top; - u32 size; - u32 alloc; + void *base; + void *top; + size_t size; + void *alloc; }; #define FM_MURAM_RES_SIZE 0x01000 @@ -95,8 +95,8 @@ struct fm_port_global_pram { #endif #define FM_FREE_POOL_ALIGN 256 -u32 fm_muram_alloc(int fm_idx, u32 size, u32 align); -u32 fm_muram_base(int fm_idx); +void *fm_muram_alloc(int fm_idx, size_t size, ulong align); +void *fm_muram_base(int fm_idx); int fm_init_common(int index, struct ccsr_fman *reg); int fm_eth_initialize(struct ccsr_fman *reg, struct fm_eth_info *info); phy_interface_t fman_port_enet_if(enum fm_port port); -- cgit v1.1 From 0f2cb9f5a0743f19a4c1d0f7e6506537dd6ef78d Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Mon, 26 Oct 2015 19:47:45 +0800 Subject: net/fm: Make the return value logic consistent with convention In convention, the '0' is a normal return value indicating there isn't an error. While some functions of FMan IM driver treat '0' as an error return value. Signed-off-by: Hou Zhiqiang Signed-off-by: Gong Qianyu Reviewed-by: York Sun --- drivers/net/fm/eth.c | 60 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/fm/eth.c b/drivers/net/fm/eth.c index 8ecfd06..728718e 100644 --- a/drivers/net/fm/eth.c +++ b/drivers/net/fm/eth.c @@ -211,7 +211,7 @@ static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth) FM_PRAM_SIZE, FM_PRAM_ALIGN); if (!pram) { printf("%s: No muram for Rx global parameter\n", __func__); - return 0; + return -ENOMEM; } fm_eth->rx_pram = pram; @@ -232,14 +232,16 @@ static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth) rx_bd_ring_base = malloc(sizeof(struct fm_port_bd) * RX_BD_RING_SIZE); if (!rx_bd_ring_base) - return 0; + return -ENOMEM; + memset(rx_bd_ring_base, 0, sizeof(struct fm_port_bd) * RX_BD_RING_SIZE); /* alloc Rx buffer from main memory */ rx_buf_pool = malloc(MAX_RXBUF_LEN * RX_BD_RING_SIZE); if (!rx_buf_pool) - return 0; + return -ENOMEM; + memset(rx_buf_pool, 0, MAX_RXBUF_LEN * RX_BD_RING_SIZE); debug("%s: rx_buf_pool = %p\n", __func__, rx_buf_pool); @@ -277,7 +279,7 @@ static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth) /* set IM parameter ram pointer to Rx Frame Queue ID */ out_be32(&bmi_rx_port->fmbm_rfqid, pram_page_offset); - return 1; + return 0; } static int fm_eth_tx_port_parameter_init(struct fm_eth *fm_eth) @@ -296,7 +298,7 @@ static int fm_eth_tx_port_parameter_init(struct fm_eth *fm_eth) FM_PRAM_SIZE, FM_PRAM_ALIGN); if (!pram) { printf("%s: No muram for Tx global parameter\n", __func__); - return 0; + return -ENOMEM; } fm_eth->tx_pram = pram; @@ -313,7 +315,8 @@ static int fm_eth_tx_port_parameter_init(struct fm_eth *fm_eth) tx_bd_ring_base = malloc(sizeof(struct fm_port_bd) * TX_BD_RING_SIZE); if (!tx_bd_ring_base) - return 0; + return -ENOMEM; + memset(tx_bd_ring_base, 0, sizeof(struct fm_port_bd) * TX_BD_RING_SIZE); /* save it to fm_eth */ @@ -344,29 +347,35 @@ static int fm_eth_tx_port_parameter_init(struct fm_eth *fm_eth) /* set IM parameter ram pointer to Tx Confirmation Frame Queue ID */ out_be32(&bmi_tx_port->fmbm_tcfqid, pram_page_offset); - return 1; + return 0; } static int fm_eth_init(struct fm_eth *fm_eth) { + int ret; - if (!fm_eth_rx_port_parameter_init(fm_eth)) - return 0; + ret = fm_eth_rx_port_parameter_init(fm_eth); + if (ret) + return ret; - if (!fm_eth_tx_port_parameter_init(fm_eth)) - return 0; + ret = fm_eth_tx_port_parameter_init(fm_eth); + if (ret) + return ret; - return 1; + return 0; } static int fm_eth_startup(struct fm_eth *fm_eth) { struct fsl_enet_mac *mac; + int ret; + mac = fm_eth->mac; /* Rx/TxBDs, Rx/TxQDs, Rx buff and parameter ram init */ - if (!fm_eth_init(fm_eth)) - return 0; + ret = fm_eth_init(fm_eth); + if (ret) + return ret; /* setup the MAC controller */ mac->init_mac(mac); @@ -381,7 +390,7 @@ static int fm_eth_startup(struct fm_eth *fm_eth) /* init bmi tx port, IM mode and disable */ bmi_tx_port_init(fm_eth->tx_port); - return 1; + return 0; } static void fmc_tx_port_graceful_stop_enable(struct fm_eth *fm_eth) @@ -628,7 +637,7 @@ static int fm_eth_init_mac(struct fm_eth *fm_eth, struct ccsr_fman *reg) /* alloc mac controller */ mac = malloc(sizeof(struct fsl_enet_mac)); if (!mac) - return 0; + return -ENOMEM; memset(mac, 0, sizeof(struct fsl_enet_mac)); /* save the mac to fm_eth struct */ @@ -643,7 +652,7 @@ static int fm_eth_init_mac(struct fm_eth *fm_eth, struct ccsr_fman *reg) init_tgec(mac, base, phyregs, MAX_RXBUF_LEN); #endif - return 1; + return 0; } static int init_phy(struct eth_device *dev) @@ -696,17 +705,18 @@ int fm_eth_initialize(struct ccsr_fman *reg, struct fm_eth_info *info) struct eth_device *dev; struct fm_eth *fm_eth; int i, num = info->num; + int ret; /* alloc eth device */ dev = (struct eth_device *)malloc(sizeof(struct eth_device)); if (!dev) - return 0; + return -ENOMEM; memset(dev, 0, sizeof(struct eth_device)); /* alloc the FMan ethernet private struct */ fm_eth = (struct fm_eth *)malloc(sizeof(struct fm_eth)); if (!fm_eth) - return 0; + return -ENOMEM; memset(fm_eth, 0, sizeof(struct fm_eth)); /* save off some things we need from the info struct */ @@ -721,8 +731,9 @@ int fm_eth_initialize(struct ccsr_fman *reg, struct fm_eth_info *info) fm_eth->max_rx_len = MAX_RXBUF_LEN; /* init global mac structure */ - if (!fm_eth_init_mac(fm_eth, reg)) - return 0; + ret = fm_eth_init_mac(fm_eth, reg); + if (ret) + return ret; /* keep same as the manual, we call FMAN1, FMAN2, DTSEC1, DTSEC2, etc */ if (fm_eth->type == FM_ETH_1G_E) @@ -743,8 +754,9 @@ int fm_eth_initialize(struct ccsr_fman *reg, struct fm_eth_info *info) fm_eth->enet_if = info->enet_if; /* startup the FM im */ - if (!fm_eth_startup(fm_eth)) - return 0; + ret = fm_eth_startup(fm_eth); + if (ret) + return ret; init_phy(dev); @@ -753,5 +765,5 @@ int fm_eth_initialize(struct ccsr_fman *reg, struct fm_eth_info *info) dev->enetaddr[i] = 0; eth_register(dev); - return 1; + return 0; } -- cgit v1.1 From 29d8c814a593d9d1b7a7361b6961d681cff1e188 Mon Sep 17 00:00:00 2001 From: Shaohui Xie Date: Mon, 26 Oct 2015 19:47:46 +0800 Subject: net: fm: bug fix when CONFIG_PHYLIB not defined codes related to phylib operations should be wrapped by CONFIG_PHYLIB. Signed-off-by: Shaohui Xie Signed-off-by: Gong Qianyu Reviewed-by: York Sun --- drivers/net/fm/eth.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/fm/eth.c b/drivers/net/fm/eth.c index 728718e..2111a11 100644 --- a/drivers/net/fm/eth.c +++ b/drivers/net/fm/eth.c @@ -95,6 +95,7 @@ static void dtsec_init_phy(struct eth_device *dev) dtsec_configure_serdes(fm_eth); } +#ifdef CONFIG_PHYLIB static int tgec_is_fibre(struct eth_device *dev) { struct fm_eth *fm = dev->priv; @@ -105,6 +106,7 @@ static int tgec_is_fibre(struct eth_device *dev) return hwconfig_arg_cmp(phyopt, "xfi"); } #endif +#endif static u16 muram_readw(u16 *addr) { @@ -483,8 +485,10 @@ static void fm_eth_halt(struct eth_device *dev) /* disable bmi Rx port */ bmi_rx_port_disable(fm_eth->rx_port); +#ifdef CONFIG_PHYLIB if (fm_eth->phydev) phy_shutdown(fm_eth->phydev); +#endif } static int fm_eth_send(struct eth_device *dev, void *buf, int len) @@ -658,13 +662,15 @@ static int fm_eth_init_mac(struct fm_eth *fm_eth, struct ccsr_fman *reg) static int init_phy(struct eth_device *dev) { struct fm_eth *fm_eth = dev->priv; +#ifdef CONFIG_PHYLIB struct phy_device *phydev = NULL; u32 supported; +#endif -#ifdef CONFIG_PHYLIB if (fm_eth->type == FM_ETH_1G_E) dtsec_init_phy(dev); +#ifdef CONFIG_PHYLIB if (fm_eth->bus) { phydev = phy_connect(fm_eth->bus, fm_eth->phyaddr, dev, fm_eth->enet_if); -- cgit v1.1 From 8225b2fd877f148a7663b93db55b235062ad4667 Mon Sep 17 00:00:00 2001 From: Shaohui Xie Date: Mon, 26 Oct 2015 19:47:47 +0800 Subject: net: Move some header files to include/ The fsl_dtsec.h & fsl_tgec.h & fsl_fman.h can be shared on both ARM and PPC, move it out of ppc to include/, and change the path in drivers accordingly. Signed-off-by: Shaohui Xie Signed-off-by: Gong Qianyu Reviewed-by: York Sun --- drivers/net/fm/dtsec.c | 2 +- drivers/net/fm/eth.c | 4 ++-- drivers/net/fm/fm.h | 2 +- drivers/net/fm/tgec.c | 2 +- drivers/net/fm/tgec_phy.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/fm/dtsec.c b/drivers/net/fm/dtsec.c index 8d3dc0e..b339a84 100644 --- a/drivers/net/fm/dtsec.c +++ b/drivers/net/fm/dtsec.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/net/fm/eth.c b/drivers/net/fm/eth.c index 2111a11..ec0a3cb 100644 --- a/drivers/net/fm/eth.c +++ b/drivers/net/fm/eth.c @@ -13,8 +13,8 @@ #include #include #include -#include -#include +#include +#include #include #include "fm.h" diff --git a/drivers/net/fm/fm.h b/drivers/net/fm/fm.h index 73c525e..fa9bc9f 100644 --- a/drivers/net/fm/fm.h +++ b/drivers/net/fm/fm.h @@ -10,7 +10,7 @@ #include #include #include -#include +#include /* Port ID */ #define OH_PORT_ID_BASE 0x01 diff --git a/drivers/net/fm/tgec.c b/drivers/net/fm/tgec.c index 5017123..8d4622f 100644 --- a/drivers/net/fm/tgec.c +++ b/drivers/net/fm/tgec.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include "fm.h" diff --git a/drivers/net/fm/tgec_phy.c b/drivers/net/fm/tgec_phy.c index 095f00c..24cb17b 100644 --- a/drivers/net/fm/tgec_phy.c +++ b/drivers/net/fm/tgec_phy.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include /* -- cgit v1.1 From bc24611ca11e276194e1edbb71070699a98389c5 Mon Sep 17 00:00:00 2001 From: Shaohui Xie Date: Mon, 26 Oct 2015 19:47:48 +0800 Subject: net/fm: Add QSGMII PCS init QSGMII PCS needed to be programmed same as SGMII PCS, and there are four ports in QSGMII PCS, port 0, 1, 2, 3, all the four ports shared port 0's MDIO controller, so when programming port 0, we continue to program other three ports. Signed-off-by: Shaohui Xie Signed-off-by: Mingkai Hu Signed-off-by: Gong Qianyu Reviewed-by: York Sun --- drivers/net/fm/eth.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/fm/eth.c b/drivers/net/fm/eth.c index ec0a3cb..eb8e936 100644 --- a/drivers/net/fm/eth.c +++ b/drivers/net/fm/eth.c @@ -41,28 +41,35 @@ static void dtsec_configure_serdes(struct fm_eth *priv) bus.priv = priv->mac->phyregs; bool sgmii_2500 = (priv->enet_if == PHY_INTERFACE_MODE_SGMII_2500) ? true : false; + int i = 0; +qsgmii_loop: /* SGMII IF mode + AN enable only for 1G SGMII, not for 2.5G */ value = PHY_SGMII_IF_MODE_SGMII; if (!sgmii_2500) value |= PHY_SGMII_IF_MODE_AN; - memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0x14, value); + memac_mdio_write(&bus, i, MDIO_DEVAD_NONE, 0x14, value); /* Dev ability according to SGMII specification */ value = PHY_SGMII_DEV_ABILITY_SGMII; - memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0x4, value); + memac_mdio_write(&bus, i, MDIO_DEVAD_NONE, 0x4, value); /* Adjust link timer for SGMII - 1.6 ms in units of 8 ns = 2 * 10^5 = 0x30d40 */ - memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0x13, 0x3); - memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0x12, 0xd40); + memac_mdio_write(&bus, i, MDIO_DEVAD_NONE, 0x13, 0x3); + memac_mdio_write(&bus, i, MDIO_DEVAD_NONE, 0x12, 0xd40); /* Restart AN */ value = PHY_SGMII_CR_DEF_VAL; if (!sgmii_2500) value |= PHY_SGMII_CR_RESET_AN; - memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0, value); + memac_mdio_write(&bus, i, MDIO_DEVAD_NONE, 0, value); + + if ((priv->enet_if == PHY_INTERFACE_MODE_QSGMII) && (i < 3)) { + i++; + goto qsgmii_loop; + } #else struct dtsec *regs = priv->mac->base; struct tsec_mii_mng *phyregs = priv->mac->phyregs; @@ -91,6 +98,7 @@ static void dtsec_init_phy(struct eth_device *dev) #endif if (fm_eth->enet_if == PHY_INTERFACE_MODE_SGMII || + fm_eth->enet_if == PHY_INTERFACE_MODE_QSGMII || fm_eth->enet_if == PHY_INTERFACE_MODE_SGMII_2500) dtsec_configure_serdes(fm_eth); } -- cgit v1.1 From 9f3183d2d69f6d392fb943d249934f8648531e7e Mon Sep 17 00:00:00 2001 From: Mingkai Hu Date: Mon, 26 Oct 2015 19:47:50 +0800 Subject: armv8/fsl_lsch3: Change arch to fsl-layerscape There are two LS series processors are built on ARMv8 Layersacpe architecture currently, LS2085A and LS1043A. They are based on ARMv8 core although use different chassis, so create fsl-layerscape to refactor the common code for the LS series processors which also paves the way for adding LS1043A platform. Signed-off-by: Mingkai Hu Signed-off-by: Hou Zhiqiang Signed-off-by: Gong Qianyu Reviewed-by: York Sun --- drivers/i2c/mxc_i2c.c | 4 ++-- drivers/misc/fsl_debug_server.c | 1 - drivers/net/ldpaa_eth/ls2085a.c | 2 -- drivers/pci/pcie_layerscape.c | 4 +++- 4 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c index 0f977d7..fa4c82f 100644 --- a/drivers/i2c/mxc_i2c.c +++ b/drivers/i2c/mxc_i2c.c @@ -523,8 +523,8 @@ static int bus_i2c_write(struct mxc_i2c_bus *i2c_bus, u8 chip, u32 addr, #endif static struct mxc_i2c_bus mxc_i2c_buses[] = { -#if defined(CONFIG_LS102XA) || defined(CONFIG_FSL_LSCH3) || \ - defined(CONFIG_VF610) +#if defined(CONFIG_LS102XA) || defined(CONFIG_VF610) || \ + defined(CONFIG_FSL_LAYERSCAPE) { 0, I2C1_BASE_ADDR, I2C_QUIRK_FLAG }, { 1, I2C2_BASE_ADDR, I2C_QUIRK_FLAG }, { 2, I2C3_BASE_ADDR, I2C_QUIRK_FLAG }, diff --git a/drivers/misc/fsl_debug_server.c b/drivers/misc/fsl_debug_server.c index a592891..98d9fbe 100644 --- a/drivers/misc/fsl_debug_server.c +++ b/drivers/misc/fsl_debug_server.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/ldpaa_eth/ls2085a.c b/drivers/net/ldpaa_eth/ls2085a.c index 6b7960a..93ed4f1 100644 --- a/drivers/net/ldpaa_eth/ls2085a.c +++ b/drivers/net/ldpaa_eth/ls2085a.c @@ -7,9 +7,7 @@ #include #include #include -#include #include -#include u32 dpmac_to_devdisr[] = { [WRIOP1_DPMAC1] = FSL_CHASSIS3_DEVDISR2_DPMAC1, diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c index 2f24a6a..4cee038 100644 --- a/drivers/pci/pcie_layerscape.c +++ b/drivers/pci/pcie_layerscape.c @@ -11,7 +11,9 @@ #include #include #include -#include +#ifdef CONFIG_FSL_LAYERSCAPE +#include +#endif #ifndef CONFIG_SYS_PCI_MEMORY_BUS #define CONFIG_SYS_PCI_MEMORY_BUS CONFIG_SYS_SDRAM_BASE -- cgit v1.1 From e82973414da105c1b14c822f12cb296f69ca2001 Mon Sep 17 00:00:00 2001 From: Shaohui Xie Date: Mon, 26 Oct 2015 19:47:54 +0800 Subject: armv8/ls1043a: Add Fman support Signed-off-by: Hou Zhiqiang Signed-off-by: Shaohui Xie Signed-off-by: Mingkai Hu Signed-off-by: Gong Qianyu Reviewed-by: York Sun --- drivers/net/fm/Makefile | 1 + drivers/net/fm/init.c | 10 +++- drivers/net/fm/ls1043.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 drivers/net/fm/ls1043.c (limited to 'drivers') diff --git a/drivers/net/fm/Makefile b/drivers/net/fm/Makefile index d052fcb..a3c9f99 100644 --- a/drivers/net/fm/Makefile +++ b/drivers/net/fm/Makefile @@ -37,3 +37,4 @@ obj-$(CONFIG_PPC_T4160) += t4240.o obj-$(CONFIG_PPC_T4080) += t4240.o obj-$(CONFIG_PPC_B4420) += b4860.o obj-$(CONFIG_PPC_B4860) += b4860.o +obj-$(CONFIG_LS1043A) += ls1043.o diff --git a/drivers/net/fm/init.c b/drivers/net/fm/init.c index b3ff4c5..3a1de59 100644 --- a/drivers/net/fm/init.c +++ b/drivers/net/fm/init.c @@ -1,13 +1,17 @@ /* - * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011-2015 Freescale Semiconductor, Inc. * * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include -#include #include +#ifdef CONFIG_FSL_LAYERSCAPE +#include +#else +#include +#endif #include "fm.h" @@ -153,7 +157,9 @@ void fm_disable_port(enum fm_port port) return; fm_info[i].enabled = 0; +#ifndef CONFIG_SYS_FMAN_V3 fman_disable_port(port); +#endif } void fm_enable_port(enum fm_port port) diff --git a/drivers/net/fm/ls1043.c b/drivers/net/fm/ls1043.c new file mode 100644 index 0000000..cf2cc95 --- /dev/null +++ b/drivers/net/fm/ls1043.c @@ -0,0 +1,119 @@ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include +#include + +#define FSL_CHASSIS2_RCWSR13_EC1 0xe0000000 /* bits 416..418 */ +#define FSL_CHASSIS2_RCWSR13_EC1_DTSEC3_RGMII 0x00000000 +#define FSL_CHASSIS2_RCWSR13_EC1_GPIO 0x20000000 +#define FSL_CHASSIS2_RCWSR13_EC1_FTM 0xa0000000 +#define FSL_CHASSIS2_RCWSR13_EC2 0x1c000000 /* bits 419..421 */ +#define FSL_CHASSIS2_RCWSR13_EC2_DTSEC4_RGMII 0x00000000 +#define FSL_CHASSIS2_RCWSR13_EC2_GPIO 0x04000000 +#define FSL_CHASSIS2_RCWSR13_EC2_1588 0x08000000 +#define FSL_CHASSIS2_RCWSR13_EC2_FTM 0x14000000 + +u32 port_to_devdisr[] = { + [FM1_DTSEC1] = FSL_CHASSIS2_DEVDISR2_DTSEC1_1, + [FM1_DTSEC2] = FSL_CHASSIS2_DEVDISR2_DTSEC1_2, + [FM1_DTSEC3] = FSL_CHASSIS2_DEVDISR2_DTSEC1_3, + [FM1_DTSEC4] = FSL_CHASSIS2_DEVDISR2_DTSEC1_4, + [FM1_DTSEC5] = FSL_CHASSIS2_DEVDISR2_DTSEC1_5, + [FM1_DTSEC6] = FSL_CHASSIS2_DEVDISR2_DTSEC1_6, + [FM1_DTSEC9] = FSL_CHASSIS2_DEVDISR2_DTSEC1_9, + [FM1_DTSEC10] = FSL_CHASSIS2_DEVDISR2_DTSEC1_10, + [FM1_10GEC1] = FSL_CHASSIS2_DEVDISR2_10GEC1_1, + [FM1_10GEC2] = FSL_CHASSIS2_DEVDISR2_10GEC1_2, + [FM1_10GEC3] = FSL_CHASSIS2_DEVDISR2_10GEC1_3, + [FM1_10GEC4] = FSL_CHASSIS2_DEVDISR2_10GEC1_4, +}; + +static int is_device_disabled(enum fm_port port) +{ + struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + u32 devdisr2 = in_be32(&gur->devdisr2); + + return port_to_devdisr[port] & devdisr2; +} + +void fman_disable_port(enum fm_port port) +{ + struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + + setbits_be32(&gur->devdisr2, port_to_devdisr[port]); +} + +phy_interface_t fman_port_enet_if(enum fm_port port) +{ + struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + u32 rcwsr13 = in_be32(&gur->rcwsr[13]); + + if (is_device_disabled(port)) { + printf("%s:%d: port(%d) is disabled\n", __func__, + __LINE__, port); + return PHY_INTERFACE_MODE_NONE; + } + + if ((port == FM1_10GEC1) && (is_serdes_configured(XFI_FM1_MAC9))) + return PHY_INTERFACE_MODE_XGMII; + + if ((port == FM1_DTSEC9) && (is_serdes_configured(XFI_FM1_MAC9))) + return PHY_INTERFACE_MODE_NONE; + + if (port == FM1_DTSEC3) + if ((rcwsr13 & FSL_CHASSIS2_RCWSR13_EC1) == + FSL_CHASSIS2_RCWSR13_EC1_DTSEC3_RGMII) { + printf("%s:%d: port(FM1_DTSEC3) is OK\n", + __func__, __LINE__); + return PHY_INTERFACE_MODE_RGMII; + } + if (port == FM1_DTSEC4) + if ((rcwsr13 & FSL_CHASSIS2_RCWSR13_EC2) == + FSL_CHASSIS2_RCWSR13_EC2_DTSEC4_RGMII) { + printf("%s:%d: port(FM1_DTSEC4) is OK\n", + __func__, __LINE__); + return PHY_INTERFACE_MODE_RGMII; + } + + /* handle SGMII */ + switch (port) { + case FM1_DTSEC1: + case FM1_DTSEC2: + if ((port == FM1_DTSEC2) && + is_serdes_configured(SGMII_2500_FM1_DTSEC2)) + return PHY_INTERFACE_MODE_SGMII_2500; + case FM1_DTSEC5: + case FM1_DTSEC6: + case FM1_DTSEC9: + if (is_serdes_configured(SGMII_FM1_DTSEC1 + port - FM1_DTSEC1)) + return PHY_INTERFACE_MODE_SGMII; + else if ((port == FM1_DTSEC9) && + is_serdes_configured(SGMII_2500_FM1_DTSEC9)) + return PHY_INTERFACE_MODE_SGMII_2500; + break; + default: + break; + } + + /* handle QSGMII */ + switch (port) { + case FM1_DTSEC1: + case FM1_DTSEC2: + case FM1_DTSEC5: + case FM1_DTSEC6: + /* only MAC 1,2,5,6 available for QSGMII */ + if (is_serdes_configured(QSGMII_FM1_A)) + return PHY_INTERFACE_MODE_QSGMII; + break; + default: + break; + } + + return PHY_INTERFACE_MODE_NONE; +} -- cgit v1.1 From 8ef0d5c43841bccc9112e160e96d6498aa94871b Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Mon, 26 Oct 2015 19:47:55 +0800 Subject: armv8/ls1043ardb: esdhc: Add esdhc support for ls1043ardb This patch adds esdhc support for ls1043ardb. Signed-off-by: Yangbo Lu Signed-off-by: Gong Qianyu Reviewed-by: York Sun --- drivers/mmc/fsl_esdhc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 0b37002..471d6ee 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -106,7 +106,7 @@ static uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data) xfertyp |= XFERTYP_RSPTYP_48; #if defined(CONFIG_MX53) || defined(CONFIG_PPC_T4240) || \ - defined(CONFIG_LS102XA) || defined(CONFIG_LS2085A) + defined(CONFIG_LS102XA) || defined(CONFIG_FSL_LAYERSCAPE) if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) xfertyp |= XFERTYP_CMDTYP_ABORT; #endif @@ -184,7 +184,7 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) int timeout; struct fsl_esdhc_cfg *cfg = mmc->priv; struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; -#ifdef CONFIG_LS2085A +#ifdef CONFIG_FSL_LAYERSCAPE dma_addr_t addr; #endif uint wml_value; @@ -197,7 +197,7 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) esdhc_clrsetbits32(®s->wml, WML_RD_WML_MASK, wml_value); #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO -#ifdef CONFIG_LS2085A +#ifdef CONFIG_FSL_LAYERSCAPE addr = virt_to_phys((void *)(data->dest)); if (upper_32_bits(addr)) printf("Error found for upper 32 bits\n"); @@ -223,7 +223,7 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) esdhc_clrsetbits32(®s->wml, WML_WR_WML_MASK, wml_value << 16); #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO -#ifdef CONFIG_LS2085A +#ifdef CONFIG_FSL_LAYERSCAPE addr = virt_to_phys((void *)(data->src)); if (upper_32_bits(addr)) printf("Error found for upper 32 bits\n"); @@ -277,7 +277,7 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) static void check_and_invalidate_dcache_range (struct mmc_cmd *cmd, struct mmc_data *data) { -#ifdef CONFIG_LS2085A +#ifdef CONFIG_FSL_LAYERSCAPE unsigned start = 0; #else unsigned start = (unsigned)data->dest ; @@ -285,7 +285,7 @@ static void check_and_invalidate_dcache_range unsigned size = roundup(ARCH_DMA_MINALIGN, data->blocks*data->blocksize); unsigned end = start+size ; -#ifdef CONFIG_LS2085A +#ifdef CONFIG_FSL_LAYERSCAPE dma_addr_t addr; addr = virt_to_phys((void *)(data->dest)); -- cgit v1.1 From e368c206079bf7835000634247f3a8bfbba599ba Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Wed, 14 Oct 2015 16:32:00 +0200 Subject: drivers/ddr/fsl_ddr: Make SR_IE configurable SR_IE(Self-refresh interrupt enable) is needed for Hardware Based Self-Refresh. Make it configurable and let board code handle the rest. Signed-off-by: Joakim Tjernlund Reviewed-by: York Sun --- drivers/ddr/fsl/ctrl_regs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c index 8367c95..8543679 100644 --- a/drivers/ddr/fsl/ctrl_regs.c +++ b/drivers/ddr/fsl/ctrl_regs.c @@ -858,7 +858,7 @@ static void set_ddr_sdram_cfg_2(const unsigned int ctrl_num, break; } } - + sr_ie = popts->self_refresh_interrupt_en; num_pr = 1; /* Make this configurable */ /* -- cgit v1.1 From b84c9c9a988f9631f547222d2d43298c57149e3a Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 23 Oct 2015 20:46:28 +0200 Subject: mmc: atmel: Silence debug output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This driver generates clearly debugging prints when changing clock speed, so silence those. Furthermore, the driver generates further prints in case a command fails to complete. The later case woud be useful, but for eMMC, command 8 can fail and it's not an error but a part of the specification. Thus, make this debug() as well. Signed-off-by: Marek Vasut Reviewed-by: Andreas Bießmann [fix checkpatch warnings] Signed-off-by: Andreas Bießmann --- drivers/mmc/gen_atmel_mci.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c index 45bcffb..a67fb50 100644 --- a/drivers/mmc/gen_atmel_mci.c +++ b/drivers/mmc/gen_atmel_mci.c @@ -48,8 +48,8 @@ static unsigned int atmel_mci_get_version(struct atmel_mci *mci) */ static void dump_cmd(u32 cmdr, u32 arg, u32 status, const char* msg) { - printf("gen_atmel_mci: CMDR %08x (%2u) ARGR %08x (SR: %08x) %s\n", - cmdr, cmdr&0x3F, arg, status, msg); + debug("gen_atmel_mci: CMDR %08x (%2u) ARGR %08x (SR: %08x) %s\n", + cmdr, cmdr & 0x3F, arg, status, msg); } /* Setup for MCI Clock and Block Size */ @@ -73,16 +73,16 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen) clkodd = clkdiv & 1; clkdiv >>= 1; - printf("mci: setting clock %u Hz, block size %u\n", - bus_hz / (clkdiv * 2 + clkodd + 2), blklen); + debug("mci: setting clock %u Hz, block size %u\n", + bus_hz / (clkdiv * 2 + clkodd + 2), blklen); } else { /* find clkdiv yielding a rate <= than requested */ for (clkdiv = 0; clkdiv < 255; clkdiv++) { if ((bus_hz / (clkdiv + 1) / 2) <= hz) break; } - printf("mci: setting clock %u Hz, block size %u\n", - (bus_hz / (clkdiv + 1)) / 2, blklen); + debug("mci: setting clock %u Hz, block size %u\n", + (bus_hz / (clkdiv + 1)) / 2, blklen); } } -- cgit v1.1 From ecfb0ff81295933584da136da792c317063f7bcc Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 23 Oct 2015 20:46:29 +0200 Subject: mmc: atmel: Fix clock configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After silencing the prints which were generated when reconfiguring the clock of the SD/MMC bus, surprisingly, the driver stopped working such that every attempt to use the SD/MMC bus caused the CPU to get totally stuck hard. It turns out that the prints generated a short delay, which was necessary for the CPU to reconfigure the clock without getting stuck. Thus, this patch adds a short delay after the clock configuration instead. Signed-off-by: Marek Vasut Reviewed-by: Andreas Bießmann --- drivers/mmc/gen_atmel_mci.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c index a67fb50..eb12bd0 100644 --- a/drivers/mmc/gen_atmel_mci.c +++ b/drivers/mmc/gen_atmel_mci.c @@ -113,6 +113,8 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen) if (mmc->card_caps & mmc->cfg->host_caps & MMC_MODE_HS) writel(MMCI_BIT(HSMODE), &mci->cfg); + udelay(50); + initialized = 1; } -- cgit v1.1 From 6b75d35949968ea2083d5778de6882e175ecc3d0 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 23 Oct 2015 20:46:30 +0200 Subject: mmc: atmel: Implement proper private data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of passing just the register area as a private data, introduce a proper struct atmel_mci_priv structure instead. This will become useful in the subsequent patch, where we eliminate the global variable from this driver. Signed-off-by: Marek Vasut Reviewed-by: Andreas Bießmann [fix free()] Signed-off-by: Andreas Bießmann --- drivers/mmc/gen_atmel_mci.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c index eb12bd0..74d53a3 100644 --- a/drivers/mmc/gen_atmel_mci.c +++ b/drivers/mmc/gen_atmel_mci.c @@ -32,6 +32,11 @@ # define MCI_BUS 0 #endif +struct atmel_mci_priv { + struct mmc_config cfg; + struct atmel_mci *mci; +}; + static int initialized = 0; /* Read Atmel MCI IP version */ @@ -55,7 +60,8 @@ static void dump_cmd(u32 cmdr, u32 arg, u32 status, const char* msg) /* Setup for MCI Clock and Block Size */ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen) { - atmel_mci_t *mci = mmc->priv; + struct atmel_mci_priv *priv = mmc->priv; + atmel_mci_t *mci = priv->mci; u32 bus_hz = get_mci_clk_rate(); u32 clkdiv = 255; unsigned int version = atmel_mci_get_version(mci); @@ -198,7 +204,8 @@ io_fail: static int mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { - atmel_mci_t *mci = mmc->priv; + struct atmel_mci_priv *priv = mmc->priv; + atmel_mci_t *mci = priv->mci; u32 cmdr; u32 error_flags = 0; u32 status; @@ -323,7 +330,8 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) /* Entered into mmc structure during driver init */ static void mci_set_ios(struct mmc *mmc) { - atmel_mci_t *mci = mmc->priv; + struct atmel_mci_priv *priv = mmc->priv; + atmel_mci_t *mci = priv->mci; int bus_width = mmc->bus_width; unsigned int version = atmel_mci_get_version(mci); int busw; @@ -359,7 +367,8 @@ static void mci_set_ios(struct mmc *mmc) /* Entered into mmc structure during driver init */ static int mci_init(struct mmc *mmc) { - atmel_mci_t *mci = mmc->priv; + struct atmel_mci_priv *priv = mmc->priv; + atmel_mci_t *mci = priv->mci; /* Initialize controller */ writel(MMCI_BIT(SWRST), &mci->cr); /* soft reset */ @@ -393,22 +402,23 @@ int atmel_mci_init(void *regs) { struct mmc *mmc; struct mmc_config *cfg; - struct atmel_mci *mci; + struct atmel_mci_priv *priv; unsigned int version; - cfg = malloc(sizeof(*cfg)); - if (cfg == NULL) - return -1; - memset(cfg, 0, sizeof(*cfg)); + priv = calloc(1, sizeof(*priv)); + if (!priv) + return -ENOMEM; - mci = (struct atmel_mci *)regs; + cfg = &priv->cfg; cfg->name = "mci"; cfg->ops = &atmel_mci_ops; + priv->mci = (struct atmel_mci *)regs; + /* need to be able to pass these in on a board by board basis */ cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; - version = atmel_mci_get_version(mci); + version = atmel_mci_get_version(priv->mci); if ((version & 0xf00) >= 0x300) { cfg->host_caps = MMC_MODE_8BIT; cfg->host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz; @@ -425,13 +435,13 @@ int atmel_mci_init(void *regs) cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; - mmc = mmc_create(cfg, regs); + mmc = mmc_create(cfg, priv); if (mmc == NULL) { - free(cfg); - return -1; + free(priv); + return -ENODEV; } - /* NOTE: possibly leaking the cfg structure */ + /* NOTE: possibly leaking the priv structure */ return 0; } -- cgit v1.1 From 877807e193340b2586bc328bb000f32fde986be4 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 23 Oct 2015 20:46:31 +0200 Subject: mmc: atmel: Zap global 'initialized' variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Global variables are bad. Get rid of this particular one, so we can correctly instantiate multiple atmel mci interfaces, without having them interfere with one another. Signed-off-by: Marek Vasut Reviewed-by: Andreas Bießmann --- drivers/mmc/gen_atmel_mci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c index 74d53a3..da870c6 100644 --- a/drivers/mmc/gen_atmel_mci.c +++ b/drivers/mmc/gen_atmel_mci.c @@ -35,10 +35,9 @@ struct atmel_mci_priv { struct mmc_config cfg; struct atmel_mci *mci; + unsigned int initialized:1; }; -static int initialized = 0; - /* Read Atmel MCI IP version */ static unsigned int atmel_mci_get_version(struct atmel_mci *mci) { @@ -121,7 +120,7 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen) udelay(50); - initialized = 1; + priv->initialized = 1; } /* Return the CMDR with flags for a given command and data packet */ @@ -210,7 +209,7 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) u32 error_flags = 0; u32 status; - if (!initialized) { + if (!priv->initialized) { puts ("MCI not initialized!\n"); return COMM_ERR; } @@ -415,6 +414,7 @@ int atmel_mci_init(void *regs) cfg->ops = &atmel_mci_ops; priv->mci = (struct atmel_mci *)regs; + priv->initialized = 0; /* need to be able to pass these in on a board by board basis */ cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; -- cgit v1.1 From 8c1b717218aff5a1eae0f045dcb64088f3728102 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 23 Oct 2015 22:55:40 +0200 Subject: lcd: atmel: Add 32bpp support for HLCDC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add 32bpp framebuffer support for the Atmel HLCDC driver. This is needed for output bpp higher than 16bpp. Signed-off-by: Marek Vasut Reviewed-by: Andreas Bießmann --- drivers/video/atmel_hlcdfb.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/video/atmel_hlcdfb.c b/drivers/video/atmel_hlcdfb.c index 0ce2370..960b474 100644 --- a/drivers/video/atmel_hlcdfb.c +++ b/drivers/video/atmel_hlcdfb.c @@ -162,6 +162,10 @@ void lcd_ctrl_init(void *lcdbase) lcdc_writel(®s->lcdc_basecfg1, LCDC_BASECFG1_RGBMODE_16BPP_RGB_565); break; + case 32: + lcdc_writel(®s->lcdc_basecfg1, + LCDC_BASECFG1_RGBMODE_24BPP_RGB_888); + break; default: BUG(); break; -- cgit v1.1 From 35d460fbc8ced954fe23812e706d3eebc1dd2b4d Mon Sep 17 00:00:00 2001 From: Przemyslaw Marczak Date: Tue, 27 Oct 2015 13:07:58 +0100 Subject: dm: pmic: add s2mps11 PMIC I/O driver This driver allows I/O operations on the Samsung S2MPS11 PMIC, which provides lots of LDO/BUCK outputs. To enable it, update defconfig with: - CONFIG_PMIC_S2MPS11 and additional, if were not defined: - CONFIG_CMD_PMIC - CONFIG_ERRNO_STR The binding info: doc/device-tree-bindings/pmic/s2mps11.txt Signed-off-by: Przemyslaw Marczak Reviewed-by: Simon Glass Tested-by: Anand Moon Signed-off-by: Minkyu Kang --- drivers/power/pmic/Kconfig | 14 ++++++++++ drivers/power/pmic/Makefile | 1 + drivers/power/pmic/s2mps11.c | 62 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 drivers/power/pmic/s2mps11.c (limited to 'drivers') diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig index 547fd1a..fb29843 100644 --- a/drivers/power/pmic/Kconfig +++ b/drivers/power/pmic/Kconfig @@ -33,6 +33,20 @@ config DM_PMIC_MAX77686 This config enables implementation of driver-model pmic uclass features for PMIC MAX77686. The driver implements read/write operations. +config PMIC_S2MPS11 + bool "Enable Driver Model for PMIC Samsung S2MPS11" + depends on DM_PMIC + ---help--- + The Samsung S2MPS11 PMIC provides: + - 38 adjustable LDO regulators + - 9 High-Efficiency Buck Converters + - 1 BuckBoost Converter + - RTC with two alarms + - Backup battery charger + - I2C Configuration Interface + This driver provides access to I/O interface only. + Binding info: doc/device-tree-bindings/pmic/s2mps11.txt + config DM_PMIC_SANDBOX bool "Enable Driver Model for emulated Sandbox PMIC " depends on DM_PMIC diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index 00fde71..91e78f8 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_DM_PMIC) += pmic-uclass.o obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o obj-$(CONFIG_DM_PMIC_PFUZE100) += pfuze100.o +obj-$(CONFIG_PMIC_S2MPS11) += s2mps11.o obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o obj-$(CONFIG_PMIC_ACT8846) += act8846.o obj-$(CONFIG_PMIC_TPS65090) += tps65090.o diff --git a/drivers/power/pmic/s2mps11.c b/drivers/power/pmic/s2mps11.c new file mode 100644 index 0000000..9d83059 --- /dev/null +++ b/drivers/power/pmic/s2mps11.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2015 Samsung Electronics + * Przemyslaw Marczak + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +static int s2mps11_reg_count(struct udevice *dev) +{ + return S2MPS11_REG_COUNT; +} + +static int s2mps11_write(struct udevice *dev, uint reg, const uint8_t *buff, + int len) +{ + int ret; + + ret = dm_i2c_write(dev, reg, buff, len); + if (ret) + error("write error to device: %p register: %#x!", dev, reg); + + return ret; +} + +static int s2mps11_read(struct udevice *dev, uint reg, uint8_t *buff, int len) +{ + int ret; + + ret = dm_i2c_read(dev, reg, buff, len); + if (ret) + error("read error from device: %p register: %#x!", dev, reg); + + return ret; +} + +static struct dm_pmic_ops s2mps11_ops = { + .reg_count = s2mps11_reg_count, + .read = s2mps11_read, + .write = s2mps11_write, +}; + +static const struct udevice_id s2mps11_ids[] = { + { .compatible = "samsung,s2mps11-pmic" }, + { } +}; + +U_BOOT_DRIVER(pmic_s2mps11) = { + .name = "s2mps11_pmic", + .id = UCLASS_PMIC, + .of_match = s2mps11_ids, + .ops = &s2mps11_ops, +}; -- cgit v1.1 From 7c816e24a4e980e2717e5c83090dec73bc4eac57 Mon Sep 17 00:00:00 2001 From: Przemyslaw Marczak Date: Tue, 27 Oct 2015 13:07:59 +0100 Subject: dm: regulator: add function device_get_supply_regulator() Some devices are supplied by configurable regulator's output. But there was no function for getting it. This commit adds function, that allows for getting the supply device by it's phandle. The returned regulator device can be used with regulator uclass's API. Signed-off-by: Przemyslaw Marczak Cc: Simon Glass Signed-off-by: Minkyu Kang --- drivers/power/regulator/regulator-uclass.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/power/regulator/regulator-uclass.c b/drivers/power/regulator/regulator-uclass.c index a5170df..4241a4c 100644 --- a/drivers/power/regulator/regulator-uclass.c +++ b/drivers/power/regulator/regulator-uclass.c @@ -138,6 +138,13 @@ int regulator_get_by_devname(const char *devname, struct udevice **devp) return uclass_get_device_by_name(UCLASS_REGULATOR, devname, devp); } +int device_get_supply_regulator(struct udevice *dev, const char *supply_name, + struct udevice **devp) +{ + return uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, + supply_name, devp); +} + int regulator_autoset(struct udevice *dev) { struct dm_regulator_uclass_platdata *uc_pdata; -- cgit v1.1 From 5decbf53006c8e2aed8e5506b3961810c1544b3c Mon Sep 17 00:00:00 2001 From: Przemyslaw Marczak Date: Tue, 27 Oct 2015 13:08:00 +0100 Subject: dm: adc: add simple ADC uclass implementation This commit adds: - new uclass id: UCLASS_ADC - new uclass driver: drivers/adc/adc-uclass.c The new uclass's API allows for ADC operation on: * single-channel with channel selection by a number * multti-channel with channel selection by bit mask ADC uclass's functions: * single-channel: - adc_start_channel() - start channel conversion - adc_channel_data() - get conversion data - adc_channel_single_shot() - start/get conversion data * multi-channel: - adc_start_channels() - start selected channels conversion - adc_channels_data() - get conversion data - adc_channels_single_shot() - start/get conversion data for channels selected by bit mask * general: - adc_stop() - stop the conversion - adc_vdd_value() - positive reference Voltage value with polarity [uV] - adc_vss_value() - negative reference Voltage value with polarity [uV] - adc_data_mask() - conversion data bit mask The device tree can provide below constraints/properties: - vdd-polarity-negative: if true: Vdd = vdd-microvolts * (-1) - vss-polarity-negative: if true: Vss = vss-microvolts * (-1) - vdd-supply: phandle to Vdd regulator's node - vss-supply: phandle to Vss regulator's node And optional, checked only if the above corresponding, doesn't exist: - vdd-microvolts: positive reference Voltage [uV] - vss-microvolts: negative reference Voltage [uV] Signed-off-by: Przemyslaw Marczak Cc: Simon Glass Signed-off-by: Minkyu Kang --- drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/adc/Kconfig | 12 ++ drivers/adc/Makefile | 8 + drivers/adc/adc-uclass.c | 409 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 432 insertions(+) create mode 100644 drivers/adc/Kconfig create mode 100644 drivers/adc/Makefile create mode 100644 drivers/adc/adc-uclass.c (limited to 'drivers') diff --git a/drivers/Kconfig b/drivers/Kconfig index ba88b5e..c481e93 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -4,6 +4,8 @@ source "drivers/core/Kconfig" # types of drivers sorted in alphabetical order +source "drivers/adc/Kconfig" + source "drivers/block/Kconfig" source "drivers/clk/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 4f49bfd..ad29a4f 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_SPL_SATA_SUPPORT) += block/ else +obj-y += adc/ obj-$(CONFIG_DM_DEMO) += demo/ obj-$(CONFIG_BIOSEMU) += bios_emulator/ obj-y += block/ diff --git a/drivers/adc/Kconfig b/drivers/adc/Kconfig new file mode 100644 index 0000000..b6e226a --- /dev/null +++ b/drivers/adc/Kconfig @@ -0,0 +1,12 @@ +config ADC + bool "Enable ADC drivers using Driver Model" + help + This enables ADC API for drivers, which allows driving ADC features + by single and multi-channel methods for: + - start/stop/get data for conversion of a single-channel selected by + a number or multi-channels selected by a bitmask + - get data mask (ADC resolution) + ADC reference Voltage supply options: + - methods for get Vdd/Vss reference Voltage values with polarity + - support supply's phandle with auto-enable + - supply polarity setting in fdt diff --git a/drivers/adc/Makefile b/drivers/adc/Makefile new file mode 100644 index 0000000..c4d9618 --- /dev/null +++ b/drivers/adc/Makefile @@ -0,0 +1,8 @@ +# +# Copyright (C) 2015 Samsung Electronics +# Przemyslaw Marczak +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_ADC) += adc-uclass.o diff --git a/drivers/adc/adc-uclass.c b/drivers/adc/adc-uclass.c new file mode 100644 index 0000000..9233fcd --- /dev/null +++ b/drivers/adc/adc-uclass.c @@ -0,0 +1,409 @@ +/* + * Copyright (C) 2015 Samsung Electronics + * Przemyslaw Marczak + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define ADC_UCLASS_PLATDATA_SIZE sizeof(struct adc_uclass_platdata) +#define CHECK_NUMBER true +#define CHECK_MASK (!CHECK_NUMBER) + +/* TODO: add support for timer uclass (for early calls) */ +#ifdef CONFIG_SANDBOX_ARCH +#define sdelay(x) udelay(x) +#else +extern void sdelay(unsigned long loops); +#endif + +static int check_channel(struct udevice *dev, int value, bool number_or_mask, + const char *caller_function) +{ + struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev); + unsigned mask = number_or_mask ? (1 << value) : value; + + /* For the real ADC hardware, some ADC channels can be inactive. + * For example if device has 4 analog channels, and only channels + * 1-st and 3-rd are valid, then channel mask is: 0b1010, so request + * with mask 0b1110 should return an error. + */ + if ((uc_pdata->channel_mask >= mask) && (uc_pdata->channel_mask & mask)) + return 0; + + printf("Error in %s/%s().\nWrong channel selection for device: %s\n", + __FILE__, caller_function, dev->name); + + return -EINVAL; +} + +static int adc_supply_enable(struct udevice *dev) +{ + struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev); + const char *supply_type; + int ret = 0; + + if (uc_pdata->vdd_supply) { + supply_type = "vdd"; + ret = regulator_set_enable(uc_pdata->vdd_supply, true); + } + + if (!ret && uc_pdata->vss_supply) { + supply_type = "vss"; + ret = regulator_set_enable(uc_pdata->vss_supply, true); + } + + if (ret) + error("%s: can't enable %s-supply!", dev->name, supply_type); + + return ret; +} + +int adc_data_mask(struct udevice *dev, unsigned int *data_mask) +{ + struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev); + + if (!uc_pdata) + return -ENOSYS; + + *data_mask = uc_pdata->data_mask; + return 0; +} + +int adc_stop(struct udevice *dev) +{ + const struct adc_ops *ops = dev_get_driver_ops(dev); + + if (!ops->stop) + return -ENOSYS; + + return ops->stop(dev); +} + +int adc_start_channel(struct udevice *dev, int channel) +{ + const struct adc_ops *ops = dev_get_driver_ops(dev); + int ret; + + if (!ops->start_channel) + return -ENOSYS; + + ret = check_channel(dev, channel, CHECK_NUMBER, __func__); + if (ret) + return ret; + + ret = adc_supply_enable(dev); + if (ret) + return ret; + + return ops->start_channel(dev, channel); +} + +int adc_start_channels(struct udevice *dev, unsigned int channel_mask) +{ + const struct adc_ops *ops = dev_get_driver_ops(dev); + int ret; + + if (!ops->start_channels) + return -ENOSYS; + + ret = check_channel(dev, channel_mask, CHECK_MASK, __func__); + if (ret) + return ret; + + ret = adc_supply_enable(dev); + if (ret) + return ret; + + return ops->start_channels(dev, channel_mask); +} + +int adc_channel_data(struct udevice *dev, int channel, unsigned int *data) +{ + struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev); + const struct adc_ops *ops = dev_get_driver_ops(dev); + unsigned int timeout_us = uc_pdata->data_timeout_us; + int ret; + + if (!ops->channel_data) + return -ENOSYS; + + ret = check_channel(dev, channel, CHECK_NUMBER, __func__); + if (ret) + return ret; + + do { + ret = ops->channel_data(dev, channel, data); + if (!ret || ret != -EBUSY) + break; + + /* TODO: use timer uclass (for early calls). */ + sdelay(5); + } while (timeout_us--); + + return ret; +} + +int adc_channels_data(struct udevice *dev, unsigned int channel_mask, + struct adc_channel *channels) +{ + struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev); + unsigned int timeout_us = uc_pdata->multidata_timeout_us; + const struct adc_ops *ops = dev_get_driver_ops(dev); + int ret; + + if (!ops->channels_data) + return -ENOSYS; + + ret = check_channel(dev, channel_mask, CHECK_MASK, __func__); + if (ret) + return ret; + + do { + ret = ops->channels_data(dev, channel_mask, channels); + if (!ret || ret != -EBUSY) + break; + + /* TODO: use timer uclass (for early calls). */ + sdelay(5); + } while (timeout_us--); + + return ret; +} + +int adc_channel_single_shot(const char *name, int channel, unsigned int *data) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_name(UCLASS_ADC, name, &dev); + if (ret) + return ret; + + ret = adc_start_channel(dev, channel); + if (ret) + return ret; + + ret = adc_channel_data(dev, channel, data); + if (ret) + return ret; + + return 0; +} + +static int _adc_channels_single_shot(struct udevice *dev, + unsigned int channel_mask, + struct adc_channel *channels) +{ + unsigned int data; + int channel, ret; + + for (channel = 0; channel <= ADC_MAX_CHANNEL; channel++) { + /* Check channel bit. */ + if (!((channel_mask >> channel) & 0x1)) + continue; + + ret = adc_start_channel(dev, channel); + if (ret) + return ret; + + ret = adc_channel_data(dev, channel, &data); + if (ret) + return ret; + + channels->id = channel; + channels->data = data; + channels++; + } + + return 0; +} + +int adc_channels_single_shot(const char *name, unsigned int channel_mask, + struct adc_channel *channels) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_name(UCLASS_ADC, name, &dev); + if (ret) + return ret; + + ret = adc_start_channels(dev, channel_mask); + if (ret) + goto try_manual; + + ret = adc_channels_data(dev, channel_mask, channels); + if (ret) + return ret; + + return 0; + +try_manual: + if (ret != -ENOSYS) + return ret; + + return _adc_channels_single_shot(dev, channel_mask, channels); +} + +static int adc_vdd_platdata_update(struct udevice *dev) +{ + struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev); + int ret; + + /* Warning! + * This function can't return supply device before its bind. + * Please pay attention to proper fdt scan sequence. If ADC device + * will bind before its supply regulator device, then the below 'get' + * will return an error. + */ + ret = device_get_supply_regulator(dev, "vdd-supply", + &uc_pdata->vdd_supply); + if (ret) + return ret; + + ret = regulator_get_value(uc_pdata->vdd_supply); + if (ret < 0) + return ret; + + uc_pdata->vdd_microvolts = ret; + + return 0; +} + +static int adc_vss_platdata_update(struct udevice *dev) +{ + struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev); + int ret; + + ret = device_get_supply_regulator(dev, "vss-supply", + &uc_pdata->vss_supply); + if (ret) + return ret; + + ret = regulator_get_value(uc_pdata->vss_supply); + if (ret < 0) + return ret; + + uc_pdata->vss_microvolts = ret; + + return 0; +} + +int adc_vdd_value(struct udevice *dev, int *uV) +{ + struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev); + int ret, value_sign = uc_pdata->vdd_polarity_negative ? -1 : 1; + + if (!uc_pdata->vdd_supply) + goto nodev; + + /* Update the regulator Value. */ + ret = adc_vdd_platdata_update(dev); + if (ret) + return ret; +nodev: + if (uc_pdata->vdd_microvolts == -ENODATA) + return -ENODATA; + + *uV = uc_pdata->vdd_microvolts * value_sign; + + return 0; +} + +int adc_vss_value(struct udevice *dev, int *uV) +{ + struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev); + int ret, value_sign = uc_pdata->vss_polarity_negative ? -1 : 1; + + if (!uc_pdata->vss_supply) + goto nodev; + + /* Update the regulator Value. */ + ret = adc_vss_platdata_update(dev); + if (ret) + return ret; +nodev: + if (uc_pdata->vss_microvolts == -ENODATA) + return -ENODATA; + + *uV = uc_pdata->vss_microvolts * value_sign; + + return 0; +} + +static int adc_vdd_platdata_set(struct udevice *dev) +{ + struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev); + int ret, offset = dev->of_offset; + const void *fdt = gd->fdt_blob; + char *prop; + + prop = "vdd-polarity-negative"; + uc_pdata->vdd_polarity_negative = fdtdec_get_bool(fdt, offset, prop); + + ret = adc_vdd_platdata_update(dev); + if (ret != -ENOENT) + return ret; + + /* No vdd-supply phandle. */ + prop = "vdd-microvolts"; + uc_pdata->vdd_microvolts = fdtdec_get_int(fdt, offset, prop, -ENODATA); + + return 0; +} + +static int adc_vss_platdata_set(struct udevice *dev) +{ + struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev); + int ret, offset = dev->of_offset; + const void *fdt = gd->fdt_blob; + char *prop; + + prop = "vss-polarity-negative"; + uc_pdata->vss_polarity_negative = fdtdec_get_bool(fdt, offset, prop); + + ret = adc_vss_platdata_update(dev); + if (ret != -ENOENT) + return ret; + + /* No vss-supply phandle. */ + prop = "vss-microvolts"; + uc_pdata->vss_microvolts = fdtdec_get_int(fdt, offset, prop, -ENODATA); + + return 0; +} + +static int adc_pre_probe(struct udevice *dev) +{ + int ret; + + /* Set ADC VDD platdata: polarity, uV, regulator (phandle). */ + ret = adc_vdd_platdata_set(dev); + if (ret) + error("%s: Can't update Vdd. Error: %d", dev->name, ret); + + /* Set ADC VSS platdata: polarity, uV, regulator (phandle). */ + ret = adc_vss_platdata_set(dev); + if (ret) + error("%s: Can't update Vss. Error: %d", dev->name, ret); + + return 0; +} + +UCLASS_DRIVER(adc) = { + .id = UCLASS_ADC, + .name = "adc", + .pre_probe = adc_pre_probe, + .per_device_platdata_auto_alloc_size = ADC_UCLASS_PLATDATA_SIZE, +}; -- cgit v1.1 From 3b3ad9015e95ccad1a06e2eed1f182c8ddc36b21 Mon Sep 17 00:00:00 2001 From: Przemyslaw Marczak Date: Tue, 27 Oct 2015 13:08:01 +0100 Subject: dm: adc: add Exynos54xx compatible ADC driver This commit adds driver for Exynos54xx ADC subsystem. The driver is implemented using driver model, amd provides ADC uclass's methods for ADC single channel operations: - adc_start_channel() - adc_channel_data() - adc_stop() The basic parameters of ADC conversion, are: - sample rate: 600KSPS - output the data as average of 8 time conversion ADC features: - sample rate: 600KSPS - resolution: 12-bit - channels: 10 (analog multiplexer) Signed-off-by: Przemyslaw Marczak Cc: Minkyu Kang Cc: Simon Glass Signed-off-by: Minkyu Kang --- drivers/adc/Kconfig | 9 +++ drivers/adc/Makefile | 1 + drivers/adc/exynos-adc.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+) create mode 100644 drivers/adc/exynos-adc.c (limited to 'drivers') diff --git a/drivers/adc/Kconfig b/drivers/adc/Kconfig index b6e226a..223b65e 100644 --- a/drivers/adc/Kconfig +++ b/drivers/adc/Kconfig @@ -10,3 +10,12 @@ config ADC - methods for get Vdd/Vss reference Voltage values with polarity - support supply's phandle with auto-enable - supply polarity setting in fdt + +config ADC_EXYNOS + bool "Enable Exynos 54xx ADC driver" + help + This enables basic driver for Exynos ADC compatible with Exynos54xx. + It provides: + - 10 analog input channels + - 12-bit resolution + - 600 KSPS of sample rate diff --git a/drivers/adc/Makefile b/drivers/adc/Makefile index c4d9618..eb85b8b 100644 --- a/drivers/adc/Makefile +++ b/drivers/adc/Makefile @@ -6,3 +6,4 @@ # obj-$(CONFIG_ADC) += adc-uclass.o +obj-$(CONFIG_ADC_EXYNOS) += exynos-adc.o diff --git a/drivers/adc/exynos-adc.c b/drivers/adc/exynos-adc.c new file mode 100644 index 0000000..534e68d --- /dev/null +++ b/drivers/adc/exynos-adc.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2015 Samsung Electronics + * Przemyslaw Marczak + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include +#include + +struct exynos_adc_priv { + int active_channel; + struct exynos_adc_v2 *regs; +}; + +int exynos_adc_channel_data(struct udevice *dev, int channel, + unsigned int *data) +{ + struct exynos_adc_priv *priv = dev_get_priv(dev); + struct exynos_adc_v2 *regs = priv->regs; + + if (channel != priv->active_channel) { + error("Requested channel is not active!"); + return -EINVAL; + } + + if (ADC_V2_GET_STATUS_FLAG(readl(®s->status)) != FLAG_CONV_END) + return -EBUSY; + + *data = readl(®s->dat) & ADC_V2_DAT_MASK; + + return 0; +} + +int exynos_adc_start_channel(struct udevice *dev, int channel) +{ + struct exynos_adc_priv *priv = dev_get_priv(dev); + struct exynos_adc_v2 *regs = priv->regs; + unsigned int cfg; + + /* Choose channel */ + cfg = readl(®s->con2); + cfg &= ~ADC_V2_CON2_CHAN_SEL_MASK; + cfg |= ADC_V2_CON2_CHAN_SEL(channel); + writel(cfg, ®s->con2); + + /* Start conversion */ + cfg = readl(®s->con1); + writel(cfg | ADC_V2_CON1_STC_EN, ®s->con1); + + priv->active_channel = channel; + + return 0; +} + +int exynos_adc_stop(struct udevice *dev) +{ + struct exynos_adc_priv *priv = dev_get_priv(dev); + struct exynos_adc_v2 *regs = priv->regs; + unsigned int cfg; + + /* Stop conversion */ + cfg = readl(®s->con1); + cfg |= ~ADC_V2_CON1_STC_EN; + + writel(cfg, ®s->con1); + + priv->active_channel = -1; + + return 0; +} + +int exynos_adc_probe(struct udevice *dev) +{ + struct exynos_adc_priv *priv = dev_get_priv(dev); + struct exynos_adc_v2 *regs = priv->regs; + unsigned int cfg; + + /* Check HW version */ + if (readl(®s->version) != ADC_V2_VERSION) { + error("This driver supports only ADC v2!"); + return -ENXIO; + } + + /* ADC Reset */ + writel(ADC_V2_CON1_SOFT_RESET, ®s->con1); + + /* Disable INT - will read status only */ + writel(0x0, ®s->int_en); + + /* CON2 - set conversion parameters */ + cfg = ADC_V2_CON2_C_TIME(3); /* Conversion times: (1 << 3) = 8 */ + cfg |= ADC_V2_CON2_OSEL(OSEL_BINARY); + cfg |= ADC_V2_CON2_ESEL(ESEL_ADC_EVAL_TIME_20CLK); + cfg |= ADC_V2_CON2_HIGHF(HIGHF_CONV_RATE_600KSPS); + writel(cfg, ®s->con2); + + priv->active_channel = -1; + + return 0; +} + +int exynos_adc_ofdata_to_platdata(struct udevice *dev) +{ + struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev); + struct exynos_adc_priv *priv = dev_get_priv(dev); + + priv->regs = (struct exynos_adc_v2 *)dev_get_addr(dev); + if (priv->regs == (struct exynos_adc_v2 *)FDT_ADDR_T_NONE) { + error("Dev: %s - can't get address!", dev->name); + return -ENODATA; + } + + uc_pdata->data_mask = ADC_V2_DAT_MASK; + uc_pdata->data_format = ADC_DATA_FORMAT_BIN; + uc_pdata->data_timeout_us = ADC_V2_CONV_TIMEOUT_US; + + /* Mask available channel bits: [0:9] */ + uc_pdata->channel_mask = (2 << ADC_V2_MAX_CHANNEL) - 1; + + return 0; +} + +static const struct adc_ops exynos_adc_ops = { + .start_channel = exynos_adc_start_channel, + .channel_data = exynos_adc_channel_data, + .stop = exynos_adc_stop, +}; + +static const struct udevice_id exynos_adc_ids[] = { + { .compatible = "samsung,exynos-adc-v2" }, + { } +}; + +U_BOOT_DRIVER(exynos_adc) = { + .name = "exynos-adc", + .id = UCLASS_ADC, + .of_match = exynos_adc_ids, + .ops = &exynos_adc_ops, + .probe = exynos_adc_probe, + .ofdata_to_platdata = exynos_adc_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct exynos_adc_priv), +}; -- cgit v1.1 From 08d6300a35bf2eb7915f0fa2fea9fa60b5075b71 Mon Sep 17 00:00:00 2001 From: Przemyslaw Marczak Date: Tue, 27 Oct 2015 13:08:06 +0100 Subject: sandbox: add ADC driver This commit adds implementation of Sandbox ADC device emulation. The device provides: - single and multi-channel conversion - 4 channels with predefined conversion output data - 16-bit resolution Signed-off-by: Przemyslaw Marczak Cc: Simon Glass Signed-off-by: Minkyu Kang --- drivers/adc/Kconfig | 9 +++ drivers/adc/Makefile | 1 + drivers/adc/sandbox.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+) create mode 100644 drivers/adc/sandbox.c (limited to 'drivers') diff --git a/drivers/adc/Kconfig b/drivers/adc/Kconfig index 223b65e..e5335f7 100644 --- a/drivers/adc/Kconfig +++ b/drivers/adc/Kconfig @@ -19,3 +19,12 @@ config ADC_EXYNOS - 10 analog input channels - 12-bit resolution - 600 KSPS of sample rate + +config ADC_SANDBOX + bool "Enable Sandbox ADC test driver" + help + This enables driver for Sandbox ADC device emulation. + It provides: + - 4 analog input channels + - 16-bit resolution + - single and multi-channel conversion mode diff --git a/drivers/adc/Makefile b/drivers/adc/Makefile index eb85b8b..cebf26d 100644 --- a/drivers/adc/Makefile +++ b/drivers/adc/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_ADC) += adc-uclass.o obj-$(CONFIG_ADC_EXYNOS) += exynos-adc.o +obj-$(CONFIG_ADC_SANDBOX) += sandbox.o diff --git a/drivers/adc/sandbox.c b/drivers/adc/sandbox.c new file mode 100644 index 0000000..3718922 --- /dev/null +++ b/drivers/adc/sandbox.c @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2015 Samsung Electronics + * Przemyslaw Marczak + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include +#include + +/** + * struct sandbox_adc_priv - sandbox ADC device's operation status and data + * + * @conversion_status - conversion status: ACTIVE (started) / INACTIVE (stopped) + * @conversion_mode - conversion mode: single or multi-channel + * @active_channel - active channel number, valid for single channel mode + * data[] - channels data + */ +struct sandbox_adc_priv { + int conversion_status; + int conversion_mode; + int active_channel_mask; + unsigned int data[4]; +}; + +int sandbox_adc_start_channel(struct udevice *dev, int channel) +{ + struct sandbox_adc_priv *priv = dev_get_priv(dev); + + /* Set single-channel mode */ + priv->conversion_mode = SANDBOX_ADC_MODE_SINGLE_CHANNEL; + /* Select channel */ + priv->active_channel_mask = 1 << channel; + /* Start conversion */ + priv->conversion_status = SANDBOX_ADC_ACTIVE; + + return 0; +} + +int sandbox_adc_start_channels(struct udevice *dev, unsigned int channel_mask) +{ + struct sandbox_adc_priv *priv = dev_get_priv(dev); + + /* Set single-channel mode */ + priv->conversion_mode = SANDBOX_ADC_MODE_MULTI_CHANNEL; + /* Select channel */ + priv->active_channel_mask = channel_mask; + /* Start conversion */ + priv->conversion_status = SANDBOX_ADC_ACTIVE; + + return 0; +} + +int sandbox_adc_channel_data(struct udevice *dev, int channel, + unsigned int *data) +{ + struct sandbox_adc_priv *priv = dev_get_priv(dev); + + /* For single-channel conversion mode, check if channel was selected */ + if ((priv->conversion_mode == SANDBOX_ADC_MODE_SINGLE_CHANNEL) && + !(priv->active_channel_mask & (1 << channel))) { + error("Request for an inactive channel!"); + return -EINVAL; + } + + /* The conversion must be started before reading the data */ + if (priv->conversion_status == SANDBOX_ADC_INACTIVE) + return -EIO; + + *data = priv->data[channel]; + + return 0; +} + +int sandbox_adc_channels_data(struct udevice *dev, unsigned int channel_mask, + struct adc_channel *channels) +{ + struct sandbox_adc_priv *priv = dev_get_priv(dev); + int i; + + /* Return error for single-channel conversion mode */ + if (priv->conversion_mode == SANDBOX_ADC_MODE_SINGLE_CHANNEL) { + error("ADC in single-channel mode!"); + return -EPERM; + } + /* Check channel selection */ + if (!(priv->active_channel_mask & channel_mask)) { + error("Request for an inactive channel!"); + return -EINVAL; + } + /* The conversion must be started before reading the data */ + if (priv->conversion_status == SANDBOX_ADC_INACTIVE) + return -EIO; + + for (i = 0; i < SANDBOX_ADC_CHANNELS; i++) { + if (!((channel_mask >> i) & 0x1)) + continue; + + channels->data = priv->data[i]; + channels->id = i; + channels++; + } + + return 0; +} + +int sandbox_adc_stop(struct udevice *dev) +{ + struct sandbox_adc_priv *priv = dev_get_priv(dev); + + /* Start conversion */ + priv->conversion_status = SANDBOX_ADC_INACTIVE; + + return 0; +} + +int sandbox_adc_probe(struct udevice *dev) +{ + struct sandbox_adc_priv *priv = dev_get_priv(dev); + + /* Stop conversion */ + priv->conversion_status = SANDBOX_ADC_INACTIVE; + /* Set single-channel mode */ + priv->conversion_mode = SANDBOX_ADC_MODE_SINGLE_CHANNEL; + /* Deselect all channels */ + priv->active_channel_mask = 0; + + /* Set sandbox test data */ + priv->data[0] = SANDBOX_ADC_CHANNEL0_DATA; + priv->data[1] = SANDBOX_ADC_CHANNEL1_DATA; + priv->data[2] = SANDBOX_ADC_CHANNEL2_DATA; + priv->data[3] = SANDBOX_ADC_CHANNEL3_DATA; + + return 0; +} + +int sandbox_adc_ofdata_to_platdata(struct udevice *dev) +{ + struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev); + + uc_pdata->data_mask = SANDBOX_ADC_DATA_MASK; + uc_pdata->data_format = ADC_DATA_FORMAT_BIN; + uc_pdata->data_timeout_us = 0; + + /* Mask available channel bits: [0:3] */ + uc_pdata->channel_mask = (1 << SANDBOX_ADC_CHANNELS) - 1; + + return 0; +} + +static const struct adc_ops sandbox_adc_ops = { + .start_channel = sandbox_adc_start_channel, + .start_channels = sandbox_adc_start_channels, + .channel_data = sandbox_adc_channel_data, + .channels_data = sandbox_adc_channels_data, + .stop = sandbox_adc_stop, +}; + +static const struct udevice_id sandbox_adc_ids[] = { + { .compatible = "sandbox,adc" }, + { } +}; + +U_BOOT_DRIVER(sandbox_adc) = { + .name = "sandbox-adc", + .id = UCLASS_ADC, + .of_match = sandbox_adc_ids, + .ops = &sandbox_adc_ops, + .probe = sandbox_adc_probe, + .ofdata_to_platdata = sandbox_adc_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct sandbox_adc_priv), +}; -- cgit v1.1 From 96094d4c46ba6f0402fd6add9b246380dae54536 Mon Sep 17 00:00:00 2001 From: Przemyslaw Marczak Date: Wed, 28 Oct 2015 15:41:50 +0100 Subject: s5p sdhci: call pinmux for card's gpio pins before use them The SD card detection depends on checking one pin state. But the pin was configured after card was detected, which is wrong. This commit fixes this, by moving call to pinmux before use the pin. Tested-on: Odroid U3 and Odroid X2. Signed-off-by: Przemyslaw Marczak Cc: Guillaume GARDET Cc: Lukasz Majewski Cc: Jaehoon Chung Cc: Minkyu Kang Cc: Simon Glass Acked-by: Jaehoon Chung Tested-by: Lukasz Majewski Signed-off-by: Minkyu Kang --- drivers/mmc/s5p_sdhci.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c index 15ecfee..44353c7 100644 --- a/drivers/mmc/s5p_sdhci.c +++ b/drivers/mmc/s5p_sdhci.c @@ -106,6 +106,12 @@ static int do_sdhci_init(struct sdhci_host *host) flag = host->bus_width == 8 ? PINMUX_FLAG_8BIT_MODE : PINMUX_FLAG_NONE; dev_id = host->index + PERIPH_ID_SDMMC0; + ret = exynos_pinmux_config(dev_id, flag); + if (ret) { + printf("external SD not configured\n"); + return ret; + } + if (dm_gpio_is_valid(&host->pwr_gpio)) { dm_gpio_set_value(&host->pwr_gpio, 1); ret = exynos_pinmux_config(dev_id, flag); @@ -121,12 +127,6 @@ static int do_sdhci_init(struct sdhci_host *host) debug("no SD card detected (%d)\n", ret); return -ENODEV; } - - ret = exynos_pinmux_config(dev_id, flag); - if (ret) { - printf("external SD not configured\n"); - return ret; - } } return s5p_sdhci_core_init(host); @@ -193,7 +193,7 @@ static int process_nodes(const void *blob, int node_list[], int count) } ret = do_sdhci_init(host); - if (ret) { + if (ret && ret != -ENODEV) { printf("%s: failed to initialize dev %d (%d)\n", __func__, i, ret); failed++; } -- cgit v1.1 From 512bdbd46a340e5d04afe9a865992b750dfd4503 Mon Sep 17 00:00:00 2001 From: Shaohui Xie Date: Fri, 11 Sep 2015 19:02:13 +0800 Subject: Powerpc: eSDHC: expand a fix to T4160 commit b8e5b07225 "Powerpc: eSDHC: Fix mmc read write err in uboot of T4240QDS board", T4160 also needs this fix. Signed-off-by: Shaohui Xie Reviewed-by: York Sun --- drivers/mmc/fsl_esdhc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 471d6ee..f36b794 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -106,7 +106,8 @@ static uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data) xfertyp |= XFERTYP_RSPTYP_48; #if defined(CONFIG_MX53) || defined(CONFIG_PPC_T4240) || \ - defined(CONFIG_LS102XA) || defined(CONFIG_FSL_LAYERSCAPE) + defined(CONFIG_LS102XA) || defined(CONFIG_FSL_LAYERSCAPE) || \ + defined(CONFIG_PPC_T4160) if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) xfertyp |= XFERTYP_CMDTYP_ABORT; #endif -- cgit v1.1 From cdc69550d21f38c99a3c2428598f1a6f126e955e Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Thu, 17 Sep 2015 10:27:12 +0800 Subject: mmc: fsl_esdhc: enable dat[4:7] for eMMC4.5 Adapter Card If adapter card type identification is supported for platform, we would enable dat[4:7] for eMMC4.5 Adapter Card. Signed-off-by: Yangbo Lu Reviewed-by: York Sun --- drivers/mmc/fsl_esdhc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index f36b794..5c20627 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -748,6 +748,9 @@ void mmc_adapter_card_type_ident(void) switch (card_id) { case QIXIS_ESDHC_ADAPTER_TYPE_EMMC45: + value = QIXIS_READ(brdcfg[5]); + value |= (QIXIS_DAT4 | QIXIS_DAT5_6_7); + QIXIS_WRITE(brdcfg[5], value); break; case QIXIS_ESDHC_ADAPTER_TYPE_SDMMC_LEGACY: break; -- cgit v1.1 From bf50be835ed1c0e2875ff7672381944eeab8695d Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Thu, 17 Sep 2015 10:27:48 +0800 Subject: mmc: fsl_esdhc: enable EVDD automatic control for SD/MMC Legacy Adapter Card When detecting SDHC Adapter Card Type 2(SD/MMC Legacy Adapter Card), enable EVDD automatic control via SDHC_VS. This could support SD card IO voltage switching for UHS-1 speed mode. Signed-off-by: Yangbo Lu Reviewed-by: York Sun --- drivers/mmc/fsl_esdhc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 5c20627..c5054d6 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -753,6 +753,9 @@ void mmc_adapter_card_type_ident(void) QIXIS_WRITE(brdcfg[5], value); break; case QIXIS_ESDHC_ADAPTER_TYPE_SDMMC_LEGACY: + value = QIXIS_READ(pwr_ctl[1]); + value |= QIXIS_EVDD_BY_SDHC_VS; + QIXIS_WRITE(pwr_ctl[1], value); break; case QIXIS_ESDHC_ADAPTER_TYPE_EMMC44: value = QIXIS_READ(brdcfg[5]); -- cgit v1.1 From 79667b7b769405ec510baf2afed566eae58ec713 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Tue, 22 Sep 2015 14:59:25 +0800 Subject: mmc: sdhci: Fix the SD clock stop sequence According to the SDHC specification, stopping the SD Clock is by setting the SD Clock Enable bit in the Clock Control register at 0, instead of setting all bits at 0. Before stopping the SD clock, we need to make sure all SD transactions to complete, so add checking the CMD and DAT bits in the Presen State register, before stopping the SD clock. Signed-off-by: Wenyou Yang --- drivers/mmc/sdhci.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index d89e302..02d71b9 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -286,9 +286,25 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, static int sdhci_set_clock(struct mmc *mmc, unsigned int clock) { struct sdhci_host *host = mmc->priv; - unsigned int div, clk, timeout; + unsigned int div, clk, timeout, reg; - sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); + /* Wait max 20 ms */ + timeout = 200; + while (sdhci_readl(host, SDHCI_PRESENT_STATE) & + (SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT)) { + if (timeout == 0) { + printf("%s: Timeout to wait cmd & data inhibit\n", + __func__); + return -1; + } + + timeout--; + udelay(100); + } + + reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + reg &= ~SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL); if (clock == 0) return 0; -- cgit v1.1 From a3b59b1523727da932b284737fbfc93a7f962125 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Mon, 2 Nov 2015 10:57:09 +0800 Subject: mmc: atmel: Add atmel sdhci support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SDHCI is introduced by sama5d2, named as Secure Digital Multimedia Card Controller(SDMMC). It supports the embedded MultiMedia Card (e.MMC) Specification V4.41, the SD Memory Card Specification V3.0, and the SDIO V3.0 specification. It is compliant with the SD Host Controller Standard V3.0 specification. Signed-off-by: Wenyou Yang Reviewed-by: Andreas Bießmann --- drivers/mmc/Makefile | 1 + drivers/mmc/atmel_sdhci.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 drivers/mmc/atmel_sdhci.c (limited to 'drivers') diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 99d0295..5d35705 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_DM_MMC) += mmc-uclass.o obj-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o +obj-$(CONFIG_ATMEL_SDHCI) += atmel_sdhci.o obj-$(CONFIG_BCM2835_SDHCI) += bcm2835_sdhci.o obj-$(CONFIG_BFIN_SDH) += bfin_sdh.o obj-$(CONFIG_DAVINCI_MMC) += davinci_mmc.o diff --git a/drivers/mmc/atmel_sdhci.c b/drivers/mmc/atmel_sdhci.c new file mode 100644 index 0000000..24b68b6 --- /dev/null +++ b/drivers/mmc/atmel_sdhci.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2015 Atmel Corporation + * Wenyou.Yang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +#define ATMEL_SDHC_MIN_FREQ 400000 + +int atmel_sdhci_init(void *regbase, u32 id) +{ + struct sdhci_host *host; + u32 max_clk, min_clk = ATMEL_SDHC_MIN_FREQ; + + host = (struct sdhci_host *)calloc(1, sizeof(struct sdhci_host)); + if (!host) { + printf("%s: sdhci_host calloc failed\n", __func__); + return -ENOMEM; + } + + host->name = "atmel_sdhci"; + host->ioaddr = regbase; + host->quirks = 0; + host->version = sdhci_readw(host, SDHCI_HOST_VERSION); + max_clk = at91_get_periph_generated_clk(id); + if (!max_clk) { + printf("%s: Failed to get the proper clock\n", __func__); + free(host); + return -ENODEV; + } + + add_sdhci(host, max_clk, min_clk); + + return 0; +} -- cgit v1.1 From b748b24fb504b4da630c6464d6704ae7758f3732 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 20 Oct 2015 18:39:29 +0200 Subject: ohci: Add missing cache-flush for hcca area We need to cache-flush the hcca area after the initial memset, otherwise on the first hc_interrupt we might see an old $random value as done_head and try to interpret that as the address for a completed td (followed by chaos). Signed-off-by: Hans de Goede --- drivers/usb/host/ohci-hcd.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 9bde2b2..ccbfc02 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -2205,6 +2205,7 @@ int ohci_register(struct udevice *dev, struct ohci_regs *regs) if (!ohci->hcca) return -ENOMEM; memset(ohci->hcca, 0, sizeof(struct ohci_hcca)); + flush_dcache_hcca(ohci->hcca); if (hc_reset(ohci) < 0) return -EIO; -- cgit v1.1 From 30e3ea4c79dd35e97d04546bd39e2468c8ba63ef Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Tue, 20 Oct 2015 15:22:00 +0530 Subject: dfu: dfu_sf: Pass duplicate devstr to parse_dev parse_dev() alters the string pointed by devstr parameter. Due to this subsequent parsing of sf entities will fail, as string pointed by devstr is no longer valid sf dev arguments. Fix this by passing pointer to the copy of the string to parse_dev instead of pointer to the actual devstr. Signed-off-by: Vignesh R Reviewed-by: Tom Rini --- drivers/dfu/dfu_sf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dfu/dfu_sf.c b/drivers/dfu/dfu_sf.c index 7646c6b..9702eee 100644 --- a/drivers/dfu/dfu_sf.c +++ b/drivers/dfu/dfu_sf.c @@ -115,8 +115,10 @@ static struct spi_flash *parse_dev(char *devstr) int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char *s) { char *st; + char *devstr_bkup = strdup(devstr); - dfu->data.sf.dev = parse_dev(devstr); + dfu->data.sf.dev = parse_dev(devstr_bkup); + free(devstr_bkup); if (!dfu->data.sf.dev) return -ENODEV; -- cgit v1.1 From 01c94c4a6ee73210096c1e363977ef0568675187 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 30 Oct 2015 16:24:06 +0100 Subject: usb: dwc3: Fix warnings on 64-bit builds Change aritmentics to use 64bit types to be compatible with 64bit builds. Signed-off-by: Michal Simek --- drivers/usb/dwc3/core.c | 7 ++++--- drivers/usb/dwc3/ep0.c | 10 +++++----- drivers/usb/dwc3/gadget.c | 10 +++++----- drivers/usb/dwc3/io.h | 4 ++-- 4 files changed, 16 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index ab3c94e..0ae3de5 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -281,7 +281,7 @@ static int dwc3_setup_scratch_buffers(struct dwc3 *dwc) return 0; err1: - dma_unmap_single((void *)dwc->scratch_addr, dwc->nr_scratch * + dma_unmap_single((void *)(uintptr_t)dwc->scratch_addr, dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); err0: @@ -296,7 +296,7 @@ static void dwc3_free_scratch_buffers(struct dwc3 *dwc) if (!dwc->nr_scratch) return; - dma_unmap_single((void *)dwc->scratch_addr, dwc->nr_scratch * + dma_unmap_single((void *)(uintptr_t)dwc->scratch_addr, dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); kfree(dwc->scratchbuf); } @@ -629,7 +629,8 @@ int dwc3_uboot_init(struct dwc3_device *dwc3_dev) dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); dwc->mem = mem; - dwc->regs = (int *)(dwc3_dev->base + DWC3_GLOBALS_REGS_START); + dwc->regs = (void *)(uintptr_t)(dwc3_dev->base + + DWC3_GLOBALS_REGS_START); /* default to highest possible threshold */ lpm_nyet_threshold = 0xff; diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index aba614f..12b133f 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -81,8 +81,8 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma, trb->ctrl |= (DWC3_TRB_CTRL_IOC | DWC3_TRB_CTRL_LST); - dwc3_flush_cache((int)buf_dma, len); - dwc3_flush_cache((int)trb, sizeof(*trb)); + dwc3_flush_cache((long)buf_dma, len); + dwc3_flush_cache((long)trb, sizeof(*trb)); if (chain) return 0; @@ -790,7 +790,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, if (!r) return; - dwc3_flush_cache((int)trb, sizeof(*trb)); + dwc3_flush_cache((long)trb, sizeof(*trb)); status = DWC3_TRB_SIZE_TRBSTS(trb->size); if (status == DWC3_TRBSTS_SETUP_PENDING) { @@ -821,7 +821,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, ur->actual += transferred; trb++; - dwc3_flush_cache((int)trb, sizeof(*trb)); + dwc3_flush_cache((long)trb, sizeof(*trb)); length = trb->size & DWC3_TRB_SIZE_MASK; ep0->free_slot = 0; @@ -831,7 +831,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, maxp); transferred = min_t(u32, ur->length - transferred, transfer_size - length); - dwc3_flush_cache((int)dwc->ep0_bounce, DWC3_EP0_BOUNCE_SIZE); + dwc3_flush_cache((long)dwc->ep0_bounce, DWC3_EP0_BOUNCE_SIZE); memcpy(buf, dwc->ep0_bounce, transferred); } else { transferred = ur->length - length; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index f3d649a..8ff949d 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -244,7 +244,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, list_del(&req->list); req->trb = NULL; - dwc3_flush_cache((int)req->request.dma, req->request.length); + dwc3_flush_cache((long)req->request.dma, req->request.length); if (req->request.status == -EINPROGRESS) req->request.status = status; @@ -771,8 +771,8 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, trb->ctrl |= DWC3_TRB_CTRL_HWO; - dwc3_flush_cache((int)dma, length); - dwc3_flush_cache((int)trb, sizeof(*trb)); + dwc3_flush_cache((long)dma, length); + dwc3_flush_cache((long)trb, sizeof(*trb)); } /* @@ -1769,7 +1769,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, slot %= DWC3_TRB_NUM; trb = &dep->trb_pool[slot]; - dwc3_flush_cache((int)trb, sizeof(*trb)); + dwc3_flush_cache((long)trb, sizeof(*trb)); __dwc3_cleanup_done_trbs(dwc, dep, req, trb, event, status); dwc3_gadget_giveback(dep, req, status); @@ -2670,7 +2670,7 @@ void dwc3_gadget_uboot_handle_interrupt(struct dwc3 *dwc) for (i = 0; i < dwc->num_event_buffers; i++) { evt = dwc->ev_buffs[i]; - dwc3_flush_cache((int)evt->buf, evt->length); + dwc3_flush_cache((long)evt->buf, evt->length); } dwc3_thread_interrupt(0, dwc); diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h index 5042a24..0d9fa22 100644 --- a/drivers/usb/dwc3/io.h +++ b/drivers/usb/dwc3/io.h @@ -23,7 +23,7 @@ #define CACHELINE_SIZE CONFIG_SYS_CACHELINE_SIZE static inline u32 dwc3_readl(void __iomem *base, u32 offset) { - u32 offs = offset - DWC3_GLOBALS_REGS_START; + unsigned long offs = offset - DWC3_GLOBALS_REGS_START; u32 value; /* @@ -38,7 +38,7 @@ static inline u32 dwc3_readl(void __iomem *base, u32 offset) static inline void dwc3_writel(void __iomem *base, u32 offset, u32 value) { - u32 offs = offset - DWC3_GLOBALS_REGS_START; + unsigned long offs = offset - DWC3_GLOBALS_REGS_START; /* * We requested the mem region starting from the Globals address -- cgit v1.1 From 32191755d75a28a88ca980c89c1fa15db4920510 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 30 Oct 2015 16:19:43 +0100 Subject: usb: lthor: Specify correct parameter for sizeof type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch removes this warning: CC drivers/usb/gadget/f_thor.o drivers/usb/gadget/f_thor.c: In function ‘thor_tx_data’: drivers/usb/gadget/f_thor.c:572:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘long unsigned int’ [-Wformat=] debug("%s: dev->in_req->length:%d to_cpy:%d\n", __func__, ^ Signed-off-by: Michal Simek --- drivers/usb/gadget/f_thor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c index ff1481b..9ed0ce3 100644 --- a/drivers/usb/gadget/f_thor.c +++ b/drivers/usb/gadget/f_thor.c @@ -569,7 +569,7 @@ static void thor_tx_data(unsigned char *data, int len) dev->in_req->length = len; - debug("%s: dev->in_req->length:%d to_cpy:%d\n", __func__, + debug("%s: dev->in_req->length:%d to_cpy:%zd\n", __func__, dev->in_req->length, sizeof(data)); status = usb_ep_queue(dev->in_ep, dev->in_req, 0); -- cgit v1.1 From f6fcebf5c181365a3c9ebc672d88121d54359eed Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 30 Oct 2015 16:21:30 +0100 Subject: usb: udc: Fix warnings on 64-bit builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cast u32 bit value to 64bit before recasting to 64bit pointer to avoid pointer from integer cast size mismatch warnings. Warning log: +../drivers/usb/gadget/udc/udc-core.c: In function ‘usb_gadget_unmap_request’: +../drivers/usb/gadget/udc/udc-core.c:68:19: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] Signed-off-by: Michal Simek --- drivers/usb/gadget/udc/udc-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c index 875e998..326757b 100644 --- a/drivers/usb/gadget/udc/udc-core.c +++ b/drivers/usb/gadget/udc/udc-core.c @@ -65,7 +65,7 @@ void usb_gadget_unmap_request(struct usb_gadget *gadget, if (req->length == 0) return; - dma_unmap_single((void *)req->dma, req->length, + dma_unmap_single((void *)(uintptr_t)req->dma, req->length, is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); } EXPORT_SYMBOL_GPL(usb_gadget_unmap_request); -- cgit v1.1 From 6bdc593e969ffe650399c32908856e0506bbae08 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 17 Oct 2015 19:41:17 -0600 Subject: dm: serial: Deal with stdout-path with an alias Sometimes stdout-path contains a UART alias along with speed, etc. For example: stdout-path = "serial0:115200n8"; Add support for decoding this. Signed-off-by: Simon Glass Signed-off-by: Michal Simek --- drivers/serial/serial-uclass.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 55011cc..842f78b 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -29,14 +29,34 @@ static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE; static void serial_find_console_or_panic(void) { + const void *blob = gd->fdt_blob; struct udevice *dev; int node; - if (CONFIG_IS_ENABLED(OF_CONTROL) && gd->fdt_blob) { + if (CONFIG_IS_ENABLED(OF_CONTROL) && blob) { /* Check for a chosen console */ - node = fdtdec_get_chosen_node(gd->fdt_blob, "stdout-path"); + node = fdtdec_get_chosen_node(blob, "stdout-path"); + if (node < 0) { + const char *str, *p, *name; + + /* + * Deal with things like + * stdout-path = "serial0:115200n8"; + * + * We need to look up the alias and then follow it to + * the correct node. + */ + str = fdtdec_get_chosen_prop(blob, "stdout-path"); + if (str) { + p = strchr(str, ':'); + name = fdt_get_alias_namelen(blob, str, + p ? p - str : strlen(str)); + if (name) + node = fdt_path_offset(blob, name); + } + } if (node < 0) - node = fdt_path_offset(gd->fdt_blob, "console"); + node = fdt_path_offset(blob, "console"); if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, &dev)) { gd->cur_serial_dev = dev; @@ -48,14 +68,14 @@ static void serial_find_console_or_panic(void) * bind it anyway. */ if (node > 0 && - !lists_bind_fdt(gd->dm_root, gd->fdt_blob, node, &dev)) { + !lists_bind_fdt(gd->dm_root, blob, node, &dev)) { if (!device_probe(dev)) { gd->cur_serial_dev = dev; return; } } } - if (!SPL_BUILD || !CONFIG_IS_ENABLED(OF_CONTROL) || !gd->fdt_blob) { + if (!SPL_BUILD || !CONFIG_IS_ENABLED(OF_CONTROL) || !blob) { /* * Try to use CONFIG_CONS_INDEX if available (it is numbered * from 1!). -- cgit v1.1 From c54c0a4c1c745a009565ceb2a5c564d4d9418476 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 17 Oct 2015 19:41:22 -0600 Subject: arm: zynq: Support the debug UART Add support for the debug UART to assist with early debugging. Enable it for Zybo as an example. Signed-off-by: Simon Glass Signed-off-by: Michal Simek --- drivers/serial/Kconfig | 7 ++++ drivers/serial/serial_zynq.c | 77 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 68 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 53b4e1b..d462244 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -91,6 +91,13 @@ config DEBUG_UART_S5P will need to provide parameters to make this work. The driver will be available until the real driver-model serial is running. +config DEBUG_UART_ZYNQ + bool "Xilinx Zynq" + help + Select this to enable a debug UART using the serial_s5p driver. You + will need to provide parameters to make this work. The driver will + be available until the real driver-model serial is running. + endchoice config DEBUG_UART_BASE diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c index 9d84290..3b12c01 100644 --- a/drivers/serial/serial_zynq.c +++ b/drivers/serial/serial_zynq.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -43,20 +44,16 @@ static struct uart_zynq *uart_zynq_ports[2] = { }; /* Set up the baud rate in gd struct */ -static void uart_zynq_serial_setbrg(const int port) +static void _uart_zynq_serial_setbrg(struct uart_zynq *regs, + unsigned long clock, unsigned long baud) { /* Calculation results. */ unsigned int calc_bauderror, bdiv, bgen; unsigned long calc_baud = 0; - unsigned long baud; - unsigned long clock = get_uart_clk(port); - struct uart_zynq *regs = uart_zynq_ports[port]; /* Covering case where input clock is so slow */ - if (clock < 1000000 && gd->baudrate > 4800) - gd->baudrate = 4800; - - baud = gd->baudrate; + if (clock < 1000000 && baud > 4800) + baud = 4800; /* master clock * Baud rate = ------------------ @@ -87,36 +84,59 @@ static void uart_zynq_serial_setbrg(const int port) writel(bgen, ®s->baud_rate_gen); } -/* Initialize the UART, with...some settings. */ -static int uart_zynq_serial_init(const int port) +/* Set up the baud rate in gd struct */ +static void uart_zynq_serial_setbrg(const int port) { + unsigned long clock = get_uart_clk(port); struct uart_zynq *regs = uart_zynq_ports[port]; - if (!regs) - return -1; + return _uart_zynq_serial_setbrg(regs, clock, gd->baudrate); +} +/* Initialize the UART, with...some settings. */ +static void _uart_zynq_serial_init(struct uart_zynq *regs) +{ /* RX/TX enabled & reset */ writel(ZYNQ_UART_CR_TX_EN | ZYNQ_UART_CR_RX_EN | ZYNQ_UART_CR_TXRST | \ ZYNQ_UART_CR_RXRST, ®s->control); writel(ZYNQ_UART_MR_PARITY_NONE, ®s->mode); /* 8 bit, no parity */ +} + +/* Initialize the UART, with...some settings. */ +static int uart_zynq_serial_init(const int port) +{ + struct uart_zynq *regs = uart_zynq_ports[port]; + + if (!regs) + return -1; + + _uart_zynq_serial_init(regs); uart_zynq_serial_setbrg(port); return 0; } +static int _uart_zynq_serial_putc(struct uart_zynq *regs, const char c) +{ + if (readl(®s->channel_sts) & ZYNQ_UART_SR_TXFULL) + return -EAGAIN; + + writel(c, ®s->tx_rx_fifo); + + return 0; +} + static void uart_zynq_serial_putc(const char c, const int port) { struct uart_zynq *regs = uart_zynq_ports[port]; - while ((readl(®s->channel_sts) & ZYNQ_UART_SR_TXFULL) != 0) + while (_uart_zynq_serial_putc(regs, c) == -EAGAIN) WATCHDOG_RESET(); if (c == '\n') { - writel('\r', ®s->tx_rx_fifo); - while ((readl(®s->channel_sts) & ZYNQ_UART_SR_TXFULL) != 0) + while (_uart_zynq_serial_putc(regs, '\r') == -EAGAIN) WATCHDOG_RESET(); } - writel(c, ®s->tx_rx_fifo); } static void uart_zynq_serial_puts(const char *s, const int port) @@ -218,3 +238,28 @@ void zynq_serial_initialize(void) serial_register(&uart_zynq_serial0_device); serial_register(&uart_zynq_serial1_device); } + +#ifdef CONFIG_DEBUG_UART_ZYNQ + +#include + +void _debug_uart_init(void) +{ + struct uart_zynq *regs = (struct uart_zynq *)CONFIG_DEBUG_UART_BASE; + + _uart_zynq_serial_init(regs); + _uart_zynq_serial_setbrg(regs, CONFIG_DEBUG_UART_CLOCK, + CONFIG_BAUDRATE); +} + +static inline void _debug_uart_putc(int ch) +{ + struct uart_zynq *regs = (struct uart_zynq *)CONFIG_DEBUG_UART_BASE; + + while (_uart_zynq_serial_putc(regs, ch) == -EAGAIN) + WATCHDOG_RESET(); +} + +DEBUG_UART_FUNCS + +#endif -- cgit v1.1 From 325c8d569ea9358ee3952984ec55961efab6d602 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 17 Oct 2015 19:41:26 -0600 Subject: arm: zynq: serial: Drop non-device-tree serial driver portions Since we use device tree in SPL also, we can drop this code. Signed-off-by: Simon Glass Signed-off-by: Michal Simek --- drivers/serial/serial_zynq.c | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c index 3b12c01..926ba51 100644 --- a/drivers/serial/serial_zynq.c +++ b/drivers/serial/serial_zynq.c @@ -195,7 +195,6 @@ DECLARE_PSSERIAL_FUNCTIONS(1); static struct serial_device uart_zynq_serial1_device = INIT_PSSERIAL_STRUCTURE(1, "ttyPS1"); -#if CONFIG_IS_ENABLED(OF_CONTROL) __weak struct serial_device *default_serial_console(void) { const void *blob = gd->fdt_blob; @@ -218,20 +217,6 @@ __weak struct serial_device *default_serial_console(void) return NULL; } -#else -__weak struct serial_device *default_serial_console(void) -{ -#if defined(CONFIG_ZYNQ_SERIAL_UART0) - if (uart_zynq_ports[0]) - return &uart_zynq_serial0_device; -#endif -#if defined(CONFIG_ZYNQ_SERIAL_UART1) - if (uart_zynq_ports[1]) - return &uart_zynq_serial1_device; -#endif - return NULL; -} -#endif void zynq_serial_initialize(void) { -- cgit v1.1 From 42800ffa7997082e2466c772bc2395dff0c95e3a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 17 Oct 2015 19:41:27 -0600 Subject: arm: zynq: Move serial driver to driver model Update this driver to use driver model and change all users. Signed-off-by: Simon Glass Signed-off-by: Michal Simek --- drivers/serial/serial_zynq.c | 163 +++++++++++++++++-------------------------- 1 file changed, 65 insertions(+), 98 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c index 926ba51..88bebed 100644 --- a/drivers/serial/serial_zynq.c +++ b/drivers/serial/serial_zynq.c @@ -6,6 +6,8 @@ */ #include +#include +#include #include #include #include @@ -18,6 +20,7 @@ DECLARE_GLOBAL_DATA_PTR; #define ZYNQ_UART_SR_TXFULL 0x00000010 /* TX FIFO full */ +#define ZYNQ_UART_SR_TXACTIVE (1 << 11) /* TX active */ #define ZYNQ_UART_SR_RXEMPTY 0x00000002 /* RX FIFO empty */ #define ZYNQ_UART_CR_TX_EN 0x00000010 /* TX enabled */ @@ -38,9 +41,8 @@ struct uart_zynq { u32 baud_rate_divider; /* 0x34 - Baud Rate Divider [7:0] */ }; -static struct uart_zynq *uart_zynq_ports[2] = { - [0] = (struct uart_zynq *)ZYNQ_SERIAL_BASEADDR0, - [1] = (struct uart_zynq *)ZYNQ_SERIAL_BASEADDR1, +struct zynq_uart_priv { + struct uart_zynq *regs; }; /* Set up the baud rate in gd struct */ @@ -84,15 +86,6 @@ static void _uart_zynq_serial_setbrg(struct uart_zynq *regs, writel(bgen, ®s->baud_rate_gen); } -/* Set up the baud rate in gd struct */ -static void uart_zynq_serial_setbrg(const int port) -{ - unsigned long clock = get_uart_clk(port); - struct uart_zynq *regs = uart_zynq_ports[port]; - - return _uart_zynq_serial_setbrg(regs, clock, gd->baudrate); -} - /* Initialize the UART, with...some settings. */ static void _uart_zynq_serial_init(struct uart_zynq *regs) { @@ -102,20 +95,6 @@ static void _uart_zynq_serial_init(struct uart_zynq *regs) writel(ZYNQ_UART_MR_PARITY_NONE, ®s->mode); /* 8 bit, no parity */ } -/* Initialize the UART, with...some settings. */ -static int uart_zynq_serial_init(const int port) -{ - struct uart_zynq *regs = uart_zynq_ports[port]; - - if (!regs) - return -1; - - _uart_zynq_serial_init(regs); - uart_zynq_serial_setbrg(port); - - return 0; -} - static int _uart_zynq_serial_putc(struct uart_zynq *regs, const char c) { if (readl(®s->channel_sts) & ZYNQ_UART_SR_TXFULL) @@ -126,103 +105,91 @@ static int _uart_zynq_serial_putc(struct uart_zynq *regs, const char c) return 0; } -static void uart_zynq_serial_putc(const char c, const int port) +int zynq_serial_setbrg(struct udevice *dev, int baudrate) { - struct uart_zynq *regs = uart_zynq_ports[port]; + struct zynq_uart_priv *priv = dev_get_priv(dev); + unsigned long clock = get_uart_clk(0); - while (_uart_zynq_serial_putc(regs, c) == -EAGAIN) - WATCHDOG_RESET(); + _uart_zynq_serial_setbrg(priv->regs, clock, baudrate); - if (c == '\n') { - while (_uart_zynq_serial_putc(regs, '\r') == -EAGAIN) - WATCHDOG_RESET(); - } + return 0; } -static void uart_zynq_serial_puts(const char *s, const int port) +static int zynq_serial_probe(struct udevice *dev) { - while (*s) - uart_zynq_serial_putc(*s++, port); -} + struct zynq_uart_priv *priv = dev_get_priv(dev); -static int uart_zynq_serial_tstc(const int port) -{ - struct uart_zynq *regs = uart_zynq_ports[port]; + _uart_zynq_serial_init(priv->regs); - return (readl(®s->channel_sts) & ZYNQ_UART_SR_RXEMPTY) == 0; + return 0; } -static int uart_zynq_serial_getc(const int port) +static int zynq_serial_getc(struct udevice *dev) { - struct uart_zynq *regs = uart_zynq_ports[port]; + struct zynq_uart_priv *priv = dev_get_priv(dev); + struct uart_zynq *regs = priv->regs; + + if (readl(®s->channel_sts) & ZYNQ_UART_SR_RXEMPTY) + return -EAGAIN; - while (!uart_zynq_serial_tstc(port)) - WATCHDOG_RESET(); return readl(®s->tx_rx_fifo); } -/* Multi serial device functions */ -#define DECLARE_PSSERIAL_FUNCTIONS(port) \ - static int uart_zynq##port##_init(void) \ - { return uart_zynq_serial_init(port); } \ - static void uart_zynq##port##_setbrg(void) \ - { return uart_zynq_serial_setbrg(port); } \ - static int uart_zynq##port##_getc(void) \ - { return uart_zynq_serial_getc(port); } \ - static int uart_zynq##port##_tstc(void) \ - { return uart_zynq_serial_tstc(port); } \ - static void uart_zynq##port##_putc(const char c) \ - { uart_zynq_serial_putc(c, port); } \ - static void uart_zynq##port##_puts(const char *s) \ - { uart_zynq_serial_puts(s, port); } - -/* Serial device descriptor */ -#define INIT_PSSERIAL_STRUCTURE(port, __name) { \ - .name = __name, \ - .start = uart_zynq##port##_init, \ - .stop = NULL, \ - .setbrg = uart_zynq##port##_setbrg, \ - .getc = uart_zynq##port##_getc, \ - .tstc = uart_zynq##port##_tstc, \ - .putc = uart_zynq##port##_putc, \ - .puts = uart_zynq##port##_puts, \ -} +static int zynq_serial_putc(struct udevice *dev, const char ch) +{ + struct zynq_uart_priv *priv = dev_get_priv(dev); -DECLARE_PSSERIAL_FUNCTIONS(0); -static struct serial_device uart_zynq_serial0_device = - INIT_PSSERIAL_STRUCTURE(0, "ttyPS0"); -DECLARE_PSSERIAL_FUNCTIONS(1); -static struct serial_device uart_zynq_serial1_device = - INIT_PSSERIAL_STRUCTURE(1, "ttyPS1"); + return _uart_zynq_serial_putc(priv->regs, ch); +} -__weak struct serial_device *default_serial_console(void) +static int zynq_serial_pending(struct udevice *dev, bool input) { - const void *blob = gd->fdt_blob; - int node; - unsigned int base_addr; + struct zynq_uart_priv *priv = dev_get_priv(dev); + struct uart_zynq *regs = priv->regs; - node = fdt_path_offset(blob, "serial0"); - if (node < 0) - return NULL; + if (input) + return !(readl(®s->channel_sts) & ZYNQ_UART_SR_RXEMPTY); + else + return !!(readl(®s->channel_sts) & ZYNQ_UART_SR_TXACTIVE); +} - base_addr = fdtdec_get_addr(blob, node, "reg"); - if (base_addr == FDT_ADDR_T_NONE) - return NULL; +static int zynq_serial_ofdata_to_platdata(struct udevice *dev) +{ + struct zynq_uart_priv *priv = dev_get_priv(dev); + fdt_addr_t addr; - if (base_addr == ZYNQ_SERIAL_BASEADDR0) - return &uart_zynq_serial0_device; + addr = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg"); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; - if (base_addr == ZYNQ_SERIAL_BASEADDR1) - return &uart_zynq_serial1_device; + priv->regs = (struct uart_zynq *)addr; - return NULL; + return 0; } -void zynq_serial_initialize(void) -{ - serial_register(&uart_zynq_serial0_device); - serial_register(&uart_zynq_serial1_device); -} +static const struct dm_serial_ops zynq_serial_ops = { + .putc = zynq_serial_putc, + .pending = zynq_serial_pending, + .getc = zynq_serial_getc, + .setbrg = zynq_serial_setbrg, +}; + +static const struct udevice_id zynq_serial_ids[] = { + { .compatible = "xlnx,xuartps" }, + { .compatible = "cdns,uart-r1p8" }, + { } +}; + +U_BOOT_DRIVER(serial_s5p) = { + .name = "serial_zynq", + .id = UCLASS_SERIAL, + .of_match = zynq_serial_ids, + .ofdata_to_platdata = zynq_serial_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct zynq_uart_priv), + .probe = zynq_serial_probe, + .ops = &zynq_serial_ops, + .flags = DM_FLAG_PRE_RELOC, +}; #ifdef CONFIG_DEBUG_UART_ZYNQ -- cgit v1.1 From c79e1c1ce9e5c1ddf6fac631e4741999f8a0cc58 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Wed, 21 Oct 2015 18:59:06 -0500 Subject: rtc: Add MCP79411 support to DS1307 rtc driver The code is from Adrian Cox, and is patterned after similar support in Linux (drivers/rtc/rtc-ds1307.c:1121-1135). This chip is used on the Cyrus board from Varisys. Signed-off-by: Andy Fleming Reviewed-by: York Sun --- drivers/rtc/Makefile | 2 +- drivers/rtc/ds1307.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 3092de1..fc38a3f 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -4,7 +4,6 @@ # # SPDX-License-Identifier: GPL-2.0+ # - #ccflags-y += -DDEBUG obj-$(CONFIG_DM_RTC) += rtc-uclass.o @@ -37,6 +36,7 @@ obj-$(CONFIG_RTC_M48T35A) += m48t35ax.o obj-$(CONFIG_RTC_MAX6900) += max6900.o obj-$(CONFIG_RTC_MC13XXX) += mc13xxx-rtc.o obj-$(CONFIG_RTC_MC146818) += mc146818.o +obj-$(CONFIG_RTC_MCP79411) += ds1307.o obj-$(CONFIG_MCFRTC) += mcfrtc.o obj-$(CONFIG_RTC_MK48T59) += mk48t59.o obj-$(CONFIG_RTC_MPC5200) += mpc5xxx.o diff --git a/drivers/rtc/ds1307.c b/drivers/rtc/ds1307.c index 03ab1a8..3be1da6 100644 --- a/drivers/rtc/ds1307.c +++ b/drivers/rtc/ds1307.c @@ -58,6 +58,10 @@ #define RTC_CTL_BIT_SQWE 0x10 /* Square Wave Enable */ #define RTC_CTL_BIT_OUT 0x80 /* Output Control */ +/* MCP7941X-specific bits */ +#define MCP7941X_BIT_ST 0x80 +#define MCP7941X_BIT_VBATEN 0x08 + static uchar rtc_read (uchar reg); static void rtc_write (uchar reg, uchar val); @@ -69,6 +73,9 @@ int rtc_get (struct rtc_time *tmp) int rel = 0; uchar sec, min, hour, mday, wday, mon, year; +#ifdef CONFIG_RTC_MCP79411 +read_rtc: +#endif sec = rtc_read (RTC_SEC_REG_ADDR); min = rtc_read (RTC_MIN_REG_ADDR); hour = rtc_read (RTC_HR_REG_ADDR); @@ -81,6 +88,7 @@ int rtc_get (struct rtc_time *tmp) "hr: %02x min: %02x sec: %02x\n", year, mon, mday, wday, hour, min, sec); +#ifdef CONFIG_RTC_DS1307 if (sec & RTC_SEC_BIT_CH) { printf ("### Warning: RTC oscillator has stopped\n"); /* clear the CH flag */ @@ -88,6 +96,23 @@ int rtc_get (struct rtc_time *tmp) rtc_read (RTC_SEC_REG_ADDR) & ~RTC_SEC_BIT_CH); rel = -1; } +#endif + +#ifdef CONFIG_RTC_MCP79411 + /* make sure that the backup battery is enabled */ + if (!(wday & MCP7941X_BIT_VBATEN)) { + rtc_write(RTC_DAY_REG_ADDR, + wday | MCP7941X_BIT_VBATEN); + } + + /* clock halted? turn it on, so clock can tick. */ + if (!(sec & MCP7941X_BIT_ST)) { + rtc_write(RTC_SEC_REG_ADDR, MCP7941X_BIT_ST); + printf("Started RTC\n"); + goto read_rtc; + } +#endif + tmp->tm_sec = bcd2bin (sec & 0x7F); tmp->tm_min = bcd2bin (min & 0x7F); @@ -121,11 +146,20 @@ int rtc_set (struct rtc_time *tmp) rtc_write (RTC_YR_REG_ADDR, bin2bcd (tmp->tm_year % 100)); rtc_write (RTC_MON_REG_ADDR, bin2bcd (tmp->tm_mon)); +#ifdef CONFIG_RTC_MCP79411 + rtc_write (RTC_DAY_REG_ADDR, + bin2bcd (tmp->tm_wday + 1) | MCP7941X_BIT_VBATEN); +#else rtc_write (RTC_DAY_REG_ADDR, bin2bcd (tmp->tm_wday + 1)); +#endif rtc_write (RTC_DATE_REG_ADDR, bin2bcd (tmp->tm_mday)); rtc_write (RTC_HR_REG_ADDR, bin2bcd (tmp->tm_hour)); rtc_write (RTC_MIN_REG_ADDR, bin2bcd (tmp->tm_min)); +#ifdef CONFIG_RTC_MCP79411 + rtc_write (RTC_SEC_REG_ADDR, bin2bcd (tmp->tm_sec) | MCP7941X_BIT_ST); +#else rtc_write (RTC_SEC_REG_ADDR, bin2bcd (tmp->tm_sec)); +#endif return 0; } -- cgit v1.1 From 98fbd71d7a4492e23377b8753cfd77add26c63ec Mon Sep 17 00:00:00 2001 From: Chin Liang See Date: Sat, 17 Oct 2015 08:31:55 -0500 Subject: spi: cadence_qspi: Ensure spi_calibration is run when sclk change Ensuring spi_calibration is run when there is a change of sclk frequency. This will ensure the qspi flash access works for high sclk frequency Signed-off-by: Chin Liang See Cc: Dinh Nguyen Cc: Dinh Nguyen Cc: Marek Vasut Cc: Stefan Roese Cc: Vikas Manocha Cc: Jagannadh Teki Cc: Pavel Machek Acked-by: Marek Vasut Reviewed-by: Jagan Teki --- drivers/spi/cadence_qspi.c | 22 +++++++++++++--------- drivers/spi/cadence_qspi.h | 1 + 2 files changed, 14 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index 34a0f46..c5a4276 100644 --- a/drivers/spi/cadence_qspi.c +++ b/drivers/spi/cadence_qspi.c @@ -37,9 +37,8 @@ static int cadence_spi_write_speed(struct udevice *bus, uint hz) } /* Calibration sequence to determine the read data capture delay register */ -static int spi_calibration(struct udevice *bus) +static int spi_calibration(struct udevice *bus, uint hz) { - struct cadence_spi_platdata *plat = bus->platdata; struct cadence_spi_priv *priv = dev_get_priv(bus); void *base = priv->regbase; u8 opcode_rdid = 0x9F; @@ -64,7 +63,7 @@ static int spi_calibration(struct udevice *bus) } /* use back the intended clock and find low range */ - cadence_spi_write_speed(bus, plat->max_hz); + cadence_spi_write_speed(bus, hz); for (i = 0; i < CQSPI_READ_CAPTURE_MAX_DELAY; i++) { /* Disable QSPI */ cadence_qspi_apb_controller_disable(base); @@ -111,7 +110,7 @@ static int spi_calibration(struct udevice *bus) (range_hi + range_lo) / 2, range_lo, range_hi); /* just to ensure we do once only when speed or chip select change */ - priv->qspi_calibrated_hz = plat->max_hz; + priv->qspi_calibrated_hz = hz; priv->qspi_calibrated_cs = spi_chip_select(bus); return 0; @@ -126,14 +125,19 @@ static int cadence_spi_set_speed(struct udevice *bus, uint hz) /* Disable QSPI */ cadence_qspi_apb_controller_disable(priv->regbase); - cadence_spi_write_speed(bus, hz); - - /* Calibration required for different SCLK speed or chip select */ - if (priv->qspi_calibrated_hz != plat->max_hz || + /* + * Calibration required for different current SCLK speed, requested + * SCLK speed or chip select + */ + if (priv->previous_hz != hz || + priv->qspi_calibrated_hz != hz || priv->qspi_calibrated_cs != spi_chip_select(bus)) { - err = spi_calibration(bus); + err = spi_calibration(bus, hz); if (err) return err; + + /* prevent calibration run when same as previous request */ + priv->previous_hz = hz; } /* Enable QSPI */ diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h index 98e57aa..2912e36 100644 --- a/drivers/spi/cadence_qspi.h +++ b/drivers/spi/cadence_qspi.h @@ -38,6 +38,7 @@ struct cadence_spi_priv { int qspi_is_init; unsigned int qspi_calibrated_hz; unsigned int qspi_calibrated_cs; + unsigned int previous_hz; }; /* Functions call declaration */ -- cgit v1.1 From 040f4ba742700529d950a92da5ddbe99d9ae335e Mon Sep 17 00:00:00 2001 From: Chin Liang See Date: Sat, 17 Oct 2015 08:32:14 -0500 Subject: spi: cadence_qspi: Fix fdt read of spi-max-frequency Fix the fdt read for spi-max-frequency as it's contained in the child node. Current state of code is always returning default value. Signed-off-by: Chin Liang See Cc: Dinh Nguyen Cc: Dinh Nguyen Cc: Marek Vasut Cc: Stefan Roese Cc: Vikas Manocha Cc: Jagannadh Teki Cc: Pavel Machek Acked-by: Marek Vasut Acked-by: Pavel Machek --- drivers/spi/cadence_qspi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index c5a4276..5756178 100644 --- a/drivers/spi/cadence_qspi.c +++ b/drivers/spi/cadence_qspi.c @@ -295,10 +295,6 @@ static int cadence_spi_ofdata_to_platdata(struct udevice *bus) plat->regbase = (void *)data[0]; plat->ahbbase = (void *)data[2]; - /* Use 500KHz as a suitable default */ - plat->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", - 500000); - /* All other paramters are embedded in the child node */ subnode = fdt_first_subnode(blob, node); if (subnode < 0) { @@ -306,6 +302,10 @@ static int cadence_spi_ofdata_to_platdata(struct udevice *bus) return -ENODEV; } + /* Use 500 KHz as a suitable default */ + plat->max_hz = fdtdec_get_uint(blob, subnode, "spi-max-frequency", + 500000); + /* Read other parameters from DT */ plat->page_size = fdtdec_get_int(blob, subnode, "page-size", 256); plat->block_size = fdtdec_get_int(blob, subnode, "block-size", 16); -- cgit v1.1 From 4e609b6cb1e6e8cb14c55fd50c73c5affcba26b5 Mon Sep 17 00:00:00 2001 From: Chin Liang See Date: Sat, 17 Oct 2015 08:32:38 -0500 Subject: spi: cadence_qspi: Ensure check for max frequency in place Ensure the intended SCLK frequency not exceeding the maximum frequency. If that happen, SCLK will set to maximum frequency. Signed-off-by: Chin Liang See Cc: Dinh Nguyen Cc: Dinh Nguyen Cc: Marek Vasut Cc: Stefan Roese Cc: Vikas Manocha Cc: Jagannadh Teki Cc: Pavel Machek Acked-by: Pavel Machek --- drivers/spi/cadence_qspi.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index 5756178..4f7fd52 100644 --- a/drivers/spi/cadence_qspi.c +++ b/drivers/spi/cadence_qspi.c @@ -122,6 +122,9 @@ static int cadence_spi_set_speed(struct udevice *bus, uint hz) struct cadence_spi_priv *priv = dev_get_priv(bus); int err; + if (hz > plat->max_hz) + hz = plat->max_hz; + /* Disable QSPI */ cadence_qspi_apb_controller_disable(priv->regbase); -- cgit v1.1 From 1caf934a0504013874238445daaea7f32c36ab04 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 3 Nov 2015 23:23:37 -0800 Subject: video: Drop DEV_FLAGS_SYSTEM flag DEV_FLAGS_SYSTEM does not have any actual meaning, hence drop it. Signed-off-by: Bin Meng --- drivers/input/cros_ec_keyb.c | 2 +- drivers/input/keyboard.c | 2 +- drivers/input/tegra-kbc.c | 2 +- drivers/net/netconsole.c | 2 +- drivers/video/cfb_console.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/input/cros_ec_keyb.c b/drivers/input/cros_ec_keyb.c index a31aa77..dd150ee 100644 --- a/drivers/input/cros_ec_keyb.c +++ b/drivers/input/cros_ec_keyb.c @@ -258,7 +258,7 @@ int drv_keyboard_init(void) memset(&dev, '\0', sizeof(dev)); strcpy(dev.name, "cros-ec-keyb"); - dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; + dev.flags = DEV_FLAGS_INPUT; dev.getc = kbd_getc; dev.tstc = kbd_tstc; dev.start = cros_ec_init_keyboard; diff --git a/drivers/input/keyboard.c b/drivers/input/keyboard.c index be0f333..ca3886a 100644 --- a/drivers/input/keyboard.c +++ b/drivers/input/keyboard.c @@ -274,7 +274,7 @@ int kbd_init (void) return -1; memset (&kbddev, 0, sizeof(kbddev)); strcpy(kbddev.name, DEVNAME); - kbddev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; + kbddev.flags = DEV_FLAGS_INPUT; kbddev.getc = kbd_getc ; kbddev.tstc = kbd_testc ; diff --git a/drivers/input/tegra-kbc.c b/drivers/input/tegra-kbc.c index c9c9fac..6b88db4 100644 --- a/drivers/input/tegra-kbc.c +++ b/drivers/input/tegra-kbc.c @@ -358,7 +358,7 @@ int drv_keyboard_init(void) memset(&dev, '\0', sizeof(dev)); strcpy(dev.name, "tegra-kbc"); - dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; + dev.flags = DEV_FLAGS_INPUT; dev.getc = kbd_getc; dev.tstc = kbd_tstc; dev.start = init_tegra_keyboard; diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index bf972dc..3500047 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -330,7 +330,7 @@ int drv_nc_init(void) memset(&dev, 0, sizeof(dev)); strcpy(dev.name, "nc"); - dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; + dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT; dev.start = nc_stdio_start; dev.putc = nc_stdio_putc; dev.puts = nc_stdio_puts; diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index aa7ca86..51cdd4d 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -2281,7 +2281,7 @@ int drv_video_init(void) memset(&console_dev, 0, sizeof(console_dev)); strcpy(console_dev.name, "vga"); console_dev.ext = DEV_EXT_VIDEO; /* Video extensions */ - console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM; + console_dev.flags = DEV_FLAGS_OUTPUT; console_dev.putc = video_putc; /* 'putc' function */ console_dev.puts = video_puts; /* 'puts' function */ -- cgit v1.1 From 4b6d09449fdeaa5659c5d277bdf133457521e70b Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 3 Nov 2015 23:23:38 -0800 Subject: video: Drop DEV_EXT_VIDEO flag DEV_EXT_VIDEO does not have any actual meaning, hence drop it. Signed-off-by: Bin Meng --- drivers/video/cfb_console.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 51cdd4d..556a55f 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -2280,7 +2280,6 @@ int drv_video_init(void) /* Init vga device */ memset(&console_dev, 0, sizeof(console_dev)); strcpy(console_dev.name, "vga"); - console_dev.ext = DEV_EXT_VIDEO; /* Video extensions */ console_dev.flags = DEV_FLAGS_OUTPUT; console_dev.putc = video_putc; /* 'putc' function */ console_dev.puts = video_puts; /* 'puts' function */ -- cgit v1.1 From f8fdb81f6cbf9387fee7a8ab82b315798a7038ba Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 5 Nov 2015 12:43:39 -0200 Subject: compat: Remove is_power_of_2() definition Use the is_power_of_2() definition from log2.h to align with the kernel implementation. Signed-off-by: Fabio Estevam Reviewed-by: Tom Rini Reviewed-by: Heiko Schocher Reviewed-by: Jagan Teki --- drivers/mtd/mtdcore.c | 2 +- drivers/mtd/ubi/build.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 2f2172b..e3f56e5 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -27,11 +27,11 @@ #include #include #else -#include #include #include #endif +#include #include #include diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index f0a3b67..f484e62 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -30,7 +30,7 @@ #include #include #else -#include +#include #endif #include #include -- cgit v1.1 From 41b358d7a7c9f29eca4a439fba0ae679100a9ad5 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 5 Nov 2015 12:43:41 -0200 Subject: sf: Add SPI protection mechanism from the kernel Add the SPI NOR protection mechanism from the kernel. This code is based on the work from Brian Norris Here is the commit details: "mtd: spi-nor: refactor block protection functions" (sha1: 62593cf40b23b523b9fc9334ca61ba6c595ebb09) Signed-off-by: Fabio Estevam Signed-off-by: Jagan Teki Reviewed-by: Tom Rini Reviewed-by: Heiko Schocher Reviewed-by: Jagan Teki Signed-off-by: Fabio Estevam --- drivers/mtd/spi/sf_internal.h | 3 + drivers/mtd/spi/sf_ops.c | 170 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+) (limited to 'drivers') diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 8a3e5ec..ac493f1 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -105,6 +105,9 @@ enum spi_nor_option_flags { #define STATUS_QEB_WINSPAN (1 << 1) #define STATUS_QEB_MXIC (1 << 6) #define STATUS_PEC (1 << 7) +#define SR_BP0 BIT(2) /* Block protect 0 */ +#define SR_BP1 BIT(3) /* Block protect 1 */ +#define SR_BP2 BIT(4) /* Block protect 2 */ /* Flash timeout values */ #define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ) diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index f2a9244..6c87ba6 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "sf_internal.h" @@ -565,3 +566,172 @@ int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, return ret; } #endif + +#ifdef CONFIG_SPI_FLASH_STMICRO +static void stm_get_locked_range(struct spi_flash *flash, u8 sr, loff_t *ofs, + u32 *len) +{ + u8 mask = SR_BP2 | SR_BP1 | SR_BP0; + int shift = ffs(mask) - 1; + int pow; + + if (!(sr & mask)) { + /* No protection */ + *ofs = 0; + *len = 0; + } else { + pow = ((sr & mask) ^ mask) >> shift; + *len = flash->size >> pow; + *ofs = flash->size - *len; + } +} + +/* + * Return 1 if the entire region is locked, 0 otherwise + */ +static int stm_is_locked_sr(struct spi_flash *flash, loff_t ofs, u32 len, + u8 sr) +{ + loff_t lock_offs; + u32 lock_len; + + stm_get_locked_range(flash, sr, &lock_offs, &lock_len); + + return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs); +} + +/* + * Check if a region of the flash is (completely) locked. See stm_lock() for + * more info. + * + * Returns 1 if entire region is locked, 0 if any portion is unlocked, and + * negative on errors. + */ +int stm_is_locked(struct spi_flash *flash, loff_t ofs, u32 len) +{ + int status; + u8 sr; + + status = spi_flash_cmd_read_status(flash, &sr); + if (status < 0) + return status; + + return stm_is_locked_sr(flash, ofs, len, sr); +} + +/* + * Lock a region of the flash. Compatible with ST Micro and similar flash. + * Supports only the block protection bits BP{0,1,2} in the status register + * (SR). Does not support these features found in newer SR bitfields: + * - TB: top/bottom protect - only handle TB=0 (top protect) + * - SEC: sector/block protect - only handle SEC=0 (block protect) + * - CMP: complement protect - only support CMP=0 (range is not complemented) + * + * Sample table portion for 8MB flash (Winbond w25q64fw): + * + * SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion + * -------------------------------------------------------------------------- + * X | X | 0 | 0 | 0 | NONE | NONE + * 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64 + * 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32 + * 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16 + * 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8 + * 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4 + * 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2 + * X | X | 1 | 1 | 1 | 8 MB | ALL + * + * Returns negative on errors, 0 on success. + */ +int stm_lock(struct spi_flash *flash, u32 ofs, size_t len) +{ + u8 status_old, status_new; + u8 mask = SR_BP2 | SR_BP1 | SR_BP0; + u8 shift = ffs(mask) - 1, pow, val; + + spi_flash_cmd_read_status(flash, &status_old); + + /* SPI NOR always locks to the end */ + if (ofs + len != flash->size) { + /* Does combined region extend to end? */ + if (!stm_is_locked_sr(flash, ofs + len, flash->size - ofs - len, + status_old)) + return -EINVAL; + len = flash->size - ofs; + } + + /* + * Need smallest pow such that: + * + * 1 / (2^pow) <= (len / size) + * + * so (assuming power-of-2 size) we do: + * + * pow = ceil(log2(size / len)) = log2(size) - floor(log2(len)) + */ + pow = ilog2(flash->size) - ilog2(len); + val = mask - (pow << shift); + if (val & ~mask) + return -EINVAL; + + /* Don't "lock" with no region! */ + if (!(val & mask)) + return -EINVAL; + + status_new = (status_old & ~mask) | val; + + /* Only modify protection if it will not unlock other areas */ + if ((status_new & mask) <= (status_old & mask)) + return -EINVAL; + + spi_flash_cmd_write_status(flash, status_new); + + return 0; +} + +/* + * Unlock a region of the flash. See stm_lock() for more info + * + * Returns negative on errors, 0 on success. + */ +int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len) +{ + uint8_t status_old, status_new; + u8 mask = SR_BP2 | SR_BP1 | SR_BP0; + u8 shift = ffs(mask) - 1, pow, val; + + spi_flash_cmd_read_status(flash, &status_old); + + /* Cannot unlock; would unlock larger region than requested */ + if (stm_is_locked_sr(flash, status_old, ofs - flash->erase_size, + flash->erase_size)) + return -EINVAL; + /* + * Need largest pow such that: + * + * 1 / (2^pow) >= (len / size) + * + * so (assuming power-of-2 size) we do: + * + * pow = floor(log2(size / len)) = log2(size) - ceil(log2(len)) + */ + pow = ilog2(flash->size) - order_base_2(flash->size - (ofs + len)); + if (ofs + len == flash->size) { + val = 0; /* fully unlocked */ + } else { + val = mask - (pow << shift); + /* Some power-of-two sizes are not supported */ + if (val & ~mask) + return -EINVAL; + } + + status_new = (status_old & ~mask) | val; + + /* Only modify protection if it will not lock other areas */ + if ((status_new & mask) >= (status_old & mask)) + return -EINVAL; + + spi_flash_cmd_write_status(flash, status_new); + + return 0; +} +#endif /* CONFIG_SPI_FLASH_STMICRO */ -- cgit v1.1 From c3c016cf75360c2a0d0a065b64b438aaf7720576 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 5 Nov 2015 12:43:42 -0200 Subject: sf: Add SPI NOR protection mechanism Many SPI flashes have protection bits (BP2, BP1 and BP0) in the status register that can protect selected regions of the SPI NOR. Take these bits into account when performing erase operations, making sure that the protected areas are skipped. Tested on a mx6qsabresd: => sf probe SF: Detected M25P32 with page size 256 Bytes, erase size 64 KiB, total 4 MiB => sf protect lock 0x3f0000 0x10000 => sf erase 0x3f0000 0x10000 offset 0x3f0000 is protected and cannot be erased SF: 65536 bytes @ 0x3f0000 Erased: ERROR => sf protect unlock 0x3f0000 0x10000 => sf erase 0x3f0000 0x10000 SF: 65536 bytes @ 0x3f0000 Erased: OK Signed-off-by: Fabio Estevam [re-worked to fit the lock common to dm and non-dm] Signed-off-by: Jagan Teki Reviewed-by: Tom Rini Reviewed-by: Heiko Schocher Reviewed-by: Jagan Teki --- drivers/mtd/spi/sf_internal.h | 9 +++++++++ drivers/mtd/spi/sf_ops.c | 14 ++++++++++++-- drivers/mtd/spi/sf_probe.c | 13 +++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index ac493f1..8793f18 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -176,6 +176,15 @@ int spi_flash_cmd_read_status(struct spi_flash *flash, u8 *rs); /* Program the status register */ int spi_flash_cmd_write_status(struct spi_flash *flash, u8 ws); +/* Lock stmicro spi flash region */ +int stm_lock(struct spi_flash *flash, u32 ofs, size_t len); + +/* Unlock stmicro spi flash region */ +int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len); + +/* Check if a stmicro spi flash region is completely locked */ +int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len); + /* Read the config register */ int spi_flash_cmd_read_config(struct spi_flash *flash, u8 *rc); diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 6c87ba6..d832464 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -268,6 +268,11 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) return -1; } + if (flash->flash_is_locked(flash, offset, len) > 0) { + printf("offset 0x%x is protected and cannot be erased\n", offset); + return -EINVAL; + } + cmd[0] = flash->erase_cmd; while (len) { erase_addr = offset; @@ -310,6 +315,11 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, page_size = flash->page_size; + if (flash->flash_is_locked(flash, offset, len) > 0) { + printf("offset 0x%x is protected and cannot be written\n", offset); + return -EINVAL; + } + cmd[0] = flash->write_cmd; for (actual = 0; actual < len; actual += chunk_len) { write_addr = offset; @@ -589,7 +599,7 @@ static void stm_get_locked_range(struct spi_flash *flash, u8 sr, loff_t *ofs, /* * Return 1 if the entire region is locked, 0 otherwise */ -static int stm_is_locked_sr(struct spi_flash *flash, loff_t ofs, u32 len, +static int stm_is_locked_sr(struct spi_flash *flash, u32 ofs, u32 len, u8 sr) { loff_t lock_offs; @@ -607,7 +617,7 @@ static int stm_is_locked_sr(struct spi_flash *flash, loff_t ofs, u32 len, * Returns 1 if entire region is locked, 0 if any portion is unlocked, and * negative on errors. */ -int stm_is_locked(struct spi_flash *flash, loff_t ofs, u32 len) +int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len) { int status; u8 sr; diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index c000c53..bc05d30 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -182,6 +182,19 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode, flash->read = spi_flash_cmd_read_ops; #endif + /* lock hooks are flash specific - assign them based on idcode0 */ + switch (idcode[0]) { +#ifdef CONFIG_SPI_FLASH_STMICRO + case SPI_FLASH_CFI_MFR_STMICRO: + flash->flash_lock = stm_lock; + flash->flash_unlock = stm_unlock; + flash->flash_is_locked = stm_is_locked; +#endif + break; + default: + debug("SF: Lock ops not supported for %02x flash\n", idcode[0]); + } + /* Compute the flash size */ flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0; /* -- cgit v1.1 From 886161a4454721a24f63a59361d4f22f15123b5a Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Thu, 29 Oct 2015 21:09:31 +0800 Subject: serial: altera_jtag_uart: use BIT macro Replace numerical bit shift with BIT macro in altera_jtag_uart :%s/(1 << nr)/BIT(nr)/g where nr = 0, 1, 2 .... 31 Signed-off-by: Thomas Chou Reviewed-by: Jagan Teki --- drivers/serial/altera_jtag_uart.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/altera_jtag_uart.c b/drivers/serial/altera_jtag_uart.c index 39d4a4e..0aa741c 100644 --- a/drivers/serial/altera_jtag_uart.c +++ b/drivers/serial/altera_jtag_uart.c @@ -22,11 +22,11 @@ struct altera_jtaguart_platdata { }; /* data register */ -#define ALTERA_JTAG_RVALID (1<<15) /* Read valid */ +#define ALTERA_JTAG_RVALID BIT(15) /* Read valid */ /* control register */ -#define ALTERA_JTAG_AC (1 << 10) /* activity indicator */ -#define ALTERA_JTAG_RRDY (1 << 12) /* read available */ +#define ALTERA_JTAG_AC BIT(10) /* activity indicator */ +#define ALTERA_JTAG_RRDY BIT(12) /* read available */ #define ALTERA_JTAG_WSPACE(d) ((d)>>16) /* Write space avail */ /* Write fifo size. FIXME: this should be extracted with sopc2dts */ #define ALTERA_JTAG_WRITE_DEPTH 64 -- cgit v1.1 From 315acd08b3c9cc9905e1ef4630387f18b37e68b4 Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Sat, 31 Oct 2015 20:52:38 +0800 Subject: serial: altera_jtag_uart: minor clean up - Moved macro definitions to top - Give spaces around the '>>' in ALTERA_JTAG_WSPACE() - Re-arrange header includes ascending order - Remove unused header linux/compiler.h - Remove the penultimate comma in of_match ids Signed-off-by: Thomas Chou Reviewed-by: Jagan Teki --- drivers/serial/altera_jtag_uart.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/altera_jtag_uart.c b/drivers/serial/altera_jtag_uart.c index 0aa741c..767603c 100644 --- a/drivers/serial/altera_jtag_uart.c +++ b/drivers/serial/altera_jtag_uart.c @@ -8,18 +8,10 @@ #include #include #include -#include -#include #include +#include -struct altera_jtaguart_regs { - u32 data; /* Data register */ - u32 control; /* Control register */ -}; - -struct altera_jtaguart_platdata { - struct altera_jtaguart_regs *regs; -}; +DECLARE_GLOBAL_DATA_PTR; /* data register */ #define ALTERA_JTAG_RVALID BIT(15) /* Read valid */ @@ -27,11 +19,18 @@ struct altera_jtaguart_platdata { /* control register */ #define ALTERA_JTAG_AC BIT(10) /* activity indicator */ #define ALTERA_JTAG_RRDY BIT(12) /* read available */ -#define ALTERA_JTAG_WSPACE(d) ((d)>>16) /* Write space avail */ +#define ALTERA_JTAG_WSPACE(d) ((d) >> 16) /* Write space avail */ /* Write fifo size. FIXME: this should be extracted with sopc2dts */ #define ALTERA_JTAG_WRITE_DEPTH 64 -DECLARE_GLOBAL_DATA_PTR; +struct altera_jtaguart_regs { + u32 data; /* Data register */ + u32 control; /* Control register */ +}; + +struct altera_jtaguart_platdata { + struct altera_jtaguart_regs *regs; +}; static int altera_jtaguart_setbrg(struct udevice *dev, int baudrate) { @@ -112,8 +111,8 @@ static const struct dm_serial_ops altera_jtaguart_ops = { }; static const struct udevice_id altera_jtaguart_ids[] = { - { .compatible = "altr,juart-1.0", }, - { } + { .compatible = "altr,juart-1.0" }, + {} }; U_BOOT_DRIVER(altera_jtaguart) = { -- cgit v1.1 From d0b1483065ed2d825553988c3ae5931bab1aa2f6 Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Thu, 29 Oct 2015 21:18:01 +0800 Subject: serial: altera_uart: use BIT macro Replace numerical bit shift with BIT macro in altera_uart :%s/(1 << nr)/BIT(nr)/g where nr = 0, 1, 2 .... 31 Signed-off-by: Thomas Chou Reviewed-by: Jagan Teki --- drivers/serial/altera_uart.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c index 4ff9fe2..7d5197a 100644 --- a/drivers/serial/altera_uart.c +++ b/drivers/serial/altera_uart.c @@ -27,9 +27,9 @@ struct altera_uart_platdata { }; /* status register */ -#define ALTERA_UART_TMT (1 << 5) /* tx empty */ -#define ALTERA_UART_TRDY (1 << 6) /* tx ready */ -#define ALTERA_UART_RRDY (1 << 7) /* rx ready */ +#define ALTERA_UART_TMT BIT(5) /* tx empty */ +#define ALTERA_UART_TRDY BIT(6) /* tx ready */ +#define ALTERA_UART_RRDY BIT(7) /* rx ready */ DECLARE_GLOBAL_DATA_PTR; -- cgit v1.1 From 892414829c7df6b70bc83652bc568c2761b0d1b4 Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Sat, 31 Oct 2015 20:53:23 +0800 Subject: serial: altera_uart: minor clean up - Moved macro definitions to top - Re-arrange header includes ascending order - Remove unused header linux/compiler.h - Remove the penultimate comma in of_match ids Signed-off-by: Thomas Chou Reviewed-by: Jagan Teki --- drivers/serial/altera_uart.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c index 7d5197a..4c4794e 100644 --- a/drivers/serial/altera_uart.c +++ b/drivers/serial/altera_uart.c @@ -8,9 +8,15 @@ #include #include #include -#include -#include #include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* status register */ +#define ALTERA_UART_TMT BIT(5) /* tx empty */ +#define ALTERA_UART_TRDY BIT(6) /* tx ready */ +#define ALTERA_UART_RRDY BIT(7) /* rx ready */ struct altera_uart_regs { u32 rxdata; /* Rx data reg */ @@ -26,13 +32,6 @@ struct altera_uart_platdata { unsigned int uartclk; }; -/* status register */ -#define ALTERA_UART_TMT BIT(5) /* tx empty */ -#define ALTERA_UART_TRDY BIT(6) /* tx ready */ -#define ALTERA_UART_RRDY BIT(7) /* rx ready */ - -DECLARE_GLOBAL_DATA_PTR; - static int altera_uart_setbrg(struct udevice *dev, int baudrate) { struct altera_uart_platdata *plat = dev->platdata; @@ -106,8 +105,8 @@ static const struct dm_serial_ops altera_uart_ops = { }; static const struct udevice_id altera_uart_ids[] = { - { .compatible = "altr,uart-1.0", }, - { } + { .compatible = "altr,uart-1.0" }, + {} }; U_BOOT_DRIVER(altera_uart) = { -- cgit v1.1 From 430b43e8ee55798232f6e1cdd4f5ae486906c3f9 Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Thu, 29 Oct 2015 21:16:39 +0800 Subject: timer: altera_timer: use BIT macro Replace numerical bit shift with BIT macro in altera_timer :%s/(1 << nr)/BIT(nr)/g where nr = 0, 1, 2 .... 31 Signed-off-by: Thomas Chou Reviewed-by: Jagan Teki --- drivers/timer/altera_timer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/timer/altera_timer.c b/drivers/timer/altera_timer.c index 2ef9ad6..288357c 100644 --- a/drivers/timer/altera_timer.c +++ b/drivers/timer/altera_timer.c @@ -31,9 +31,9 @@ struct altera_timer_platdata { }; /* control register */ -#define ALTERA_TIMER_CONT (1 << 1) /* Continuous mode */ -#define ALTERA_TIMER_START (1 << 2) /* Start timer */ -#define ALTERA_TIMER_STOP (1 << 3) /* Stop timer */ +#define ALTERA_TIMER_CONT BIT(1) /* Continuous mode */ +#define ALTERA_TIMER_START BIT(2) /* Start timer */ +#define ALTERA_TIMER_STOP BIT(3) /* Stop timer */ static int altera_timer_get_count(struct udevice *dev, unsigned long *count) { -- cgit v1.1 From 1235e5a56ee61c9e986f4cd1a4e555c1a151e35a Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Sat, 31 Oct 2015 20:54:16 +0800 Subject: timer: altera_timer: minor clean up - Moved macro definitions to top - Remove the penultimate comma in of_match ids Signed-off-by: Thomas Chou Reviewed-by: Jagan Teki --- drivers/timer/altera_timer.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/timer/altera_timer.c b/drivers/timer/altera_timer.c index 288357c..46a598a 100644 --- a/drivers/timer/altera_timer.c +++ b/drivers/timer/altera_timer.c @@ -16,6 +16,11 @@ DECLARE_GLOBAL_DATA_PTR; +/* control register */ +#define ALTERA_TIMER_CONT BIT(1) /* Continuous mode */ +#define ALTERA_TIMER_START BIT(2) /* Start timer */ +#define ALTERA_TIMER_STOP BIT(3) /* Stop timer */ + struct altera_timer_regs { u32 status; /* Timer status reg */ u32 control; /* Timer control reg */ @@ -30,11 +35,6 @@ struct altera_timer_platdata { unsigned long clock_rate; }; -/* control register */ -#define ALTERA_TIMER_CONT BIT(1) /* Continuous mode */ -#define ALTERA_TIMER_START BIT(2) /* Start timer */ -#define ALTERA_TIMER_STOP BIT(3) /* Stop timer */ - static int altera_timer_get_count(struct udevice *dev, unsigned long *count) { struct altera_timer_platdata *plat = dev->platdata; @@ -88,8 +88,8 @@ static const struct timer_ops altera_timer_ops = { }; static const struct udevice_id altera_timer_ids[] = { - { .compatible = "altr,timer-1.0", }, - { } + { .compatible = "altr,timer-1.0" }, + {} }; U_BOOT_DRIVER(altera_timer) = { -- cgit v1.1 From 687dbff2cf78fa990276c57dfa36f1f7bbbc7e2a Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Sat, 31 Oct 2015 20:54:53 +0800 Subject: misc: altera_sysid: minor clean up - Remove the penultimate comma in of_match ids Signed-off-by: Thomas Chou Reviewed-by: Jagan Teki --- drivers/misc/altera_sysid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/altera_sysid.c b/drivers/misc/altera_sysid.c index 249b273..737520f 100644 --- a/drivers/misc/altera_sysid.c +++ b/drivers/misc/altera_sysid.c @@ -87,8 +87,8 @@ static const struct misc_ops altera_sysid_ops = { }; static const struct udevice_id altera_sysid_ids[] = { - { .compatible = "altr,sysid-1.0", }, - { } + { .compatible = "altr,sysid-1.0" }, + {} }; U_BOOT_DRIVER(altera_sysid) = { -- cgit v1.1 From ddf34c26065aea2bfdac448189b9c5f919063d79 Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Sat, 31 Oct 2015 20:55:48 +0800 Subject: spi: altera_spi: minor clean up - Remove the penultimate comma in of_match ids Signed-off-by: Thomas Chou Reviewed-by: Jagan Teki --- drivers/spi/altera_spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/altera_spi.c b/drivers/spi/altera_spi.c index e49949b..3e09592 100644 --- a/drivers/spi/altera_spi.c +++ b/drivers/spi/altera_spi.c @@ -193,8 +193,8 @@ static const struct dm_spi_ops altera_spi_ops = { }; static const struct udevice_id altera_spi_ids[] = { - { .compatible = "altr,spi-1.0", }, - { } + { .compatible = "altr,spi-1.0" }, + {} }; U_BOOT_DRIVER(altera_spi) = { -- cgit v1.1 From 933529ce15a49a25c00dffd4c1988ce9206a9226 Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Tue, 3 Nov 2015 14:18:27 +0800 Subject: altera_jtag_uart: Adjust the declaration of debug_uart_init() Follow commit 97b059730218 ("debug_uart: Adjust the declaration of debug_uart_init()") Signed-off-by: Thomas Chou Reviewed-by: Marek Vasut Reviewed-by: Chin Liang See --- drivers/serial/altera_jtag_uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/altera_jtag_uart.c b/drivers/serial/altera_jtag_uart.c index 767603c..c77bea3 100644 --- a/drivers/serial/altera_jtag_uart.c +++ b/drivers/serial/altera_jtag_uart.c @@ -130,7 +130,7 @@ U_BOOT_DRIVER(altera_jtaguart) = { #include -void debug_uart_init(void) +static inline void _debug_uart_init(void) { } -- cgit v1.1 From e03c17d053025c56d04282be0baf5b2969b6f4a0 Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Tue, 3 Nov 2015 14:19:02 +0800 Subject: altera_uart: Adjust the declaration of debug_uart_init() Follow commit 97b059730218 ("debug_uart: Adjust the declaration of debug_uart_init()") Signed-off-by: Thomas Chou Reviewed-by: Marek Vasut Reviewed-by: Chin Liang See --- drivers/serial/altera_uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c index 4c4794e..5d76c33 100644 --- a/drivers/serial/altera_uart.c +++ b/drivers/serial/altera_uart.c @@ -124,7 +124,7 @@ U_BOOT_DRIVER(altera_uart) = { #include -void debug_uart_init(void) +static inline void _debug_uart_init(void) { struct altera_uart_regs *regs = (void *)CONFIG_DEBUG_UART_BASE; u32 div; -- cgit v1.1 From fba54a5d612eb0c2b2f0276c95d77f209a6ea980 Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Fri, 6 Nov 2015 09:36:06 +0800 Subject: net: altera_tse: remove unused macro and regs def Remove unused macro and regs def. Signed-off-by: Thomas Chou Reviewed-by: Marek Vasut Reviewed-by: Chin Liang See Acked-by: Joe Hershberger --- drivers/net/altera_tse.h | 104 ++--------------------------------------------- 1 file changed, 3 insertions(+), 101 deletions(-) (limited to 'drivers') diff --git a/drivers/net/altera_tse.h b/drivers/net/altera_tse.h index 08c4f66..f289bff 100644 --- a/drivers/net/altera_tse.h +++ b/drivers/net/altera_tse.h @@ -14,20 +14,12 @@ #define __packed_1_ __attribute__ ((packed, aligned(1))) /* SGDMA Stuff */ -#define ALT_SGDMA_STATUS_ERROR_MSK (0x00000001) -#define ALT_SGDMA_STATUS_EOP_ENCOUNTERED_MSK (0x00000002) -#define ALT_SGDMA_STATUS_DESC_COMPLETED_MSK (0x00000004) -#define ALT_SGDMA_STATUS_CHAIN_COMPLETED_MSK (0x00000008) #define ALT_SGDMA_STATUS_BUSY_MSK (0x00000010) #define ALT_SGDMA_CONTROL_RUN_MSK (0x00000020) #define ALT_SGDMA_CONTROL_STOP_DMA_ER_MSK (0x00000040) #define ALT_SGDMA_CONTROL_SOFTWARERESET_MSK (0x00010000) -#define ALTERA_TSE_SGDMA_INTR_MASK (ALT_SGDMA_CONTROL_IE_CHAIN_COMPLETED_MSK \ - | ALT_SGDMA_STATUS_DESC_COMPLETED_MSK \ - | ALT_SGDMA_CONTROL_IE_GLOBAL_MSK) - /* * Descriptor control bit masks & offsets * @@ -38,7 +30,6 @@ #define ALT_SGDMA_DESCRIPTOR_CONTROL_GENERATE_EOP_MSK (0x00000001) #define ALT_SGDMA_DESCRIPTOR_CONTROL_READ_FIXED_ADDRESS_MSK (0x00000002) #define ALT_SGDMA_DESCRIPTOR_CONTROL_WRITE_FIXED_ADDRESS_MSK (0x00000004) -#define ALT_SGDMA_DESCRIPTOR_CONTROL_ATLANTIC_CHANNEL_MSK (0x00000008) #define ALT_SGDMA_DESCRIPTOR_CONTROL_OWNED_BY_HW_MSK (0x00000080) /* @@ -48,15 +39,7 @@ * The following bit-offsets are expressed relative to the LSB of * the status register bitfield. */ -#define ALT_SGDMA_DESCRIPTOR_STATUS_E_CRC_MSK (0x00000001) -#define ALT_SGDMA_DESCRIPTOR_STATUS_E_PARITY_MSK (0x00000002) -#define ALT_SGDMA_DESCRIPTOR_STATUS_E_OVERFLOW_MSK (0x00000004) -#define ALT_SGDMA_DESCRIPTOR_STATUS_E_SYNC_MSK (0x00000008) -#define ALT_SGDMA_DESCRIPTOR_STATUS_E_UEOP_MSK (0x00000010) -#define ALT_SGDMA_DESCRIPTOR_STATUS_E_MEOP_MSK (0x00000020) -#define ALT_SGDMA_DESCRIPTOR_STATUS_E_MSOP_MSK (0x00000040) #define ALT_SGDMA_DESCRIPTOR_STATUS_TERMINATED_BY_EOP_MSK (0x00000080) -#define ALT_SGDMA_DESCRIPTOR_STATUS_ERROR_MSK (0x0000007F) /* * The SGDMA controller buffer descriptor allocates @@ -104,37 +87,10 @@ struct alt_sgdma_registers { /* TSE Stuff */ #define ALTERA_TSE_CMD_TX_ENA_MSK (0x00000001) #define ALTERA_TSE_CMD_RX_ENA_MSK (0x00000002) -#define ALTERA_TSE_CMD_XON_GEN_MSK (0x00000004) #define ALTERA_TSE_CMD_ETH_SPEED_MSK (0x00000008) -#define ALTERA_TSE_CMD_PROMIS_EN_MSK (0x00000010) -#define ALTERA_TSE_CMD_PAD_EN_MSK (0x00000020) -#define ALTERA_TSE_CMD_CRC_FWD_MSK (0x00000040) -#define ALTERA_TSE_CMD_PAUSE_FWD_MSK (0x00000080) -#define ALTERA_TSE_CMD_PAUSE_IGNORE_MSK (0x00000100) -#define ALTERA_TSE_CMD_TX_ADDR_INS_MSK (0x00000200) #define ALTERA_TSE_CMD_HD_ENA_MSK (0x00000400) -#define ALTERA_TSE_CMD_EXCESS_COL_MSK (0x00000800) -#define ALTERA_TSE_CMD_LATE_COL_MSK (0x00001000) #define ALTERA_TSE_CMD_SW_RESET_MSK (0x00002000) -#define ALTERA_TSE_CMD_MHASH_SEL_MSK (0x00004000) -#define ALTERA_TSE_CMD_LOOPBACK_MSK (0x00008000) -/* Bits (18:16) = address select */ -#define ALTERA_TSE_CMD_TX_ADDR_SEL_MSK (0x00070000) -#define ALTERA_TSE_CMD_MAGIC_ENA_MSK (0x00080000) -#define ALTERA_TSE_CMD_SLEEP_MSK (0x00100000) -#define ALTERA_TSE_CMD_WAKEUP_MSK (0x00200000) -#define ALTERA_TSE_CMD_XOFF_GEN_MSK (0x00400000) -#define ALTERA_TSE_CMD_CNTL_FRM_ENA_MSK (0x00800000) -#define ALTERA_TSE_CMD_NO_LENGTH_CHECK_MSK (0x01000000) #define ALTERA_TSE_CMD_ENA_10_MSK (0x02000000) -#define ALTERA_TSE_CMD_RX_ERR_DISC_MSK (0x04000000) -/* Bits (30..27) reserved */ -#define ALTERA_TSE_CMD_CNT_RESET_MSK (0x80000000) - -#define ALTERA_TSE_TX_CMD_STAT_TX_SHIFT16 (0x00040000) -#define ALTERA_TSE_TX_CMD_STAT_OMIT_CRC (0x00020000) - -#define ALTERA_TSE_RX_CMD_STAT_RX_SHIFT16 (0x02000000) #define ALT_TSE_SW_RESET_TIMEOUT (3 * CONFIG_SYS_HZ) #define ALT_TSE_SGDMA_BUSY_TIMEOUT (3 * CONFIG_SYS_HZ) @@ -160,67 +116,13 @@ struct alt_tse_mac { unsigned int mdio_phy0_addr; unsigned int mdio_phy1_addr; - /* only if 100/1000 BaseX PCS, reserved otherwise */ - unsigned int reservedx44[5]; - - unsigned int reg_read_access_status; - unsigned int min_tx_ipg_length; - - /* IEEE 802.3 oEntity Managed Object Support */ - unsigned int aMACID_1; /*The MAC addresses */ - unsigned int aMACID_2; - unsigned int aFramesTransmittedOK; - unsigned int aFramesReceivedOK; - unsigned int aFramesCheckSequenceErrors; - unsigned int aAlignmentErrors; - unsigned int aOctetsTransmittedOK; - unsigned int aOctetsReceivedOK; - - /* IEEE 802.3 oPausedEntity Managed Object Support */ - unsigned int aTxPAUSEMACCtrlFrames; - unsigned int aRxPAUSEMACCtrlFrames; - - /* IETF MIB (MIB-II) Object Support */ - unsigned int ifInErrors; - unsigned int ifOutErrors; - unsigned int ifInUcastPkts; - unsigned int ifInMulticastPkts; - unsigned int ifInBroadcastPkts; - unsigned int ifOutDiscards; - unsigned int ifOutUcastPkts; - unsigned int ifOutMulticastPkts; - unsigned int ifOutBroadcastPkts; - - /* IETF RMON MIB Object Support */ - unsigned int etherStatsDropEvent; - unsigned int etherStatsOctets; - unsigned int etherStatsPkts; - unsigned int etherStatsUndersizePkts; - unsigned int etherStatsOversizePkts; - unsigned int etherStatsPkts64Octets; - unsigned int etherStatsPkts65to127Octets; - unsigned int etherStatsPkts128to255Octets; - unsigned int etherStatsPkts256to511Octets; - unsigned int etherStatsPkts512to1023Octets; - unsigned int etherStatsPkts1024to1518Octets; - - unsigned int etherStatsPkts1519toXOctets; - unsigned int etherStatsJabbers; - unsigned int etherStatsFragments; - - unsigned int reservedxE4; + unsigned int reserved1[0x29]; /*FIFO control register. */ unsigned int tx_cmd_stat; unsigned int rx_cmd_stat; - unsigned int ipaccTxConf; - unsigned int ipaccRxConf; - unsigned int ipaccRxStat; - unsigned int ipaccRxStatSum; - - /*Multicast address resolution table */ - unsigned int hash_table[64]; + unsigned int reserved2[0x44]; /*Registers 0 to 31 within PHY device 0/1 */ unsigned int mdio_phy0[0x20]; @@ -236,7 +138,7 @@ struct alt_tse_mac { unsigned int supp_mac_addr_3_0; unsigned int supp_mac_addr_3_1; - unsigned int reservedx320[56]; + unsigned int reserved3[0x38]; }; struct altera_tse_priv { -- cgit v1.1 From 2cd0a52ece530f790c5cf661180f91e5c0b57117 Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Fri, 6 Nov 2015 09:36:26 +0800 Subject: net: altera_tse: use data type u32 for regs and desc Use data type u32/u16/u8 for regs and desc, as it is more portable. Signed-off-by: Thomas Chou Reviewed-by: Marek Vasut Reviewed-by: Chin Liang See Acked-by: Joe Hershberger --- drivers/net/altera_tse.c | 16 ++++---- drivers/net/altera_tse.h | 104 +++++++++++++++++++++++------------------------ 2 files changed, 60 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/net/altera_tse.c b/drivers/net/altera_tse.c index 319983c..394503f 100644 --- a/drivers/net/altera_tse.c +++ b/drivers/net/altera_tse.c @@ -27,12 +27,12 @@ static inline void alt_sgdma_construct_descriptor( struct alt_sgdma_descriptor *next, void *read_addr, void *write_addr, - unsigned short length_or_eop, + u16 length_or_eop, int generate_eop, int read_fixed, int write_fixed_or_sop) { - unsigned char val; + u8 val; /* * Mark the "next" descriptor as "not" owned by hardware. This prevents @@ -100,7 +100,7 @@ static int alt_sgdma_wait_transfer(struct alt_sgdma_registers *regs) static int alt_sgdma_start_transfer(struct alt_sgdma_registers *regs, struct alt_sgdma_descriptor *desc) { - unsigned int val; + u32 val; /* Point the controller at the descriptor */ writel(virt_to_phys(desc), ®s->next_descriptor_pointer); @@ -121,7 +121,7 @@ static void tse_adjust_link(struct altera_tse_priv *priv, struct phy_device *phydev) { struct alt_tse_mac *mac_dev = priv->mac_dev; - unsigned int refvar; + u32 refvar; if (!phydev->link) { debug("%s: No link.\n", phydev->dev->name); @@ -230,7 +230,7 @@ static void altera_tse_stop(struct udevice *dev) struct alt_sgdma_registers *rx_sgdma = priv->sgdma_rx; struct alt_sgdma_registers *tx_sgdma = priv->sgdma_tx; struct alt_sgdma_descriptor *rx_desc = priv->rx_desc; - unsigned int status; + u32 status; int ret; ulong ctime; @@ -266,7 +266,7 @@ static int tse_mdio_read(struct mii_dev *bus, int addr, int devad, int reg) { struct altera_tse_priv *priv = bus->priv; struct alt_tse_mac *mac_dev = priv->mac_dev; - unsigned int value; + u32 value; /* set mdio address */ writel(addr, &mac_dev->mdio_phy1_addr); @@ -337,7 +337,7 @@ static int altera_tse_write_hwaddr(struct udevice *dev) struct alt_tse_mac *mac_dev = priv->mac_dev; struct eth_pdata *pdata = dev_get_platdata(dev); u8 *hwaddr = pdata->enetaddr; - unsigned int mac_lo, mac_hi; + u32 mac_lo, mac_hi; mac_lo = (hwaddr[3] << 24) | (hwaddr[2] << 16) | (hwaddr[1] << 8) | hwaddr[0]; @@ -362,7 +362,7 @@ static int altera_tse_start(struct udevice *dev) { struct altera_tse_priv *priv = dev_get_priv(dev); struct alt_tse_mac *mac_dev = priv->mac_dev; - unsigned int val; + u32 val; int ret; /* need to create sgdma */ diff --git a/drivers/net/altera_tse.h b/drivers/net/altera_tse.h index f289bff..a96351a 100644 --- a/drivers/net/altera_tse.h +++ b/drivers/net/altera_tse.h @@ -54,34 +54,34 @@ * */ struct alt_sgdma_descriptor { - unsigned int source; /* the address of data to be read. */ - unsigned int source_pad; + u32 source; /* the address of data to be read. */ + u32 source_pad; - unsigned int destination; /* the address to write data */ - unsigned int destination_pad; + u32 destination; /* the address to write data */ + u32 destination_pad; - unsigned int next; /* the next descriptor in the list. */ - unsigned int next_pad; + u32 next; /* the next descriptor in the list. */ + u32 next_pad; - unsigned short bytes_to_transfer; /* the number of bytes to transfer */ - unsigned char read_burst; - unsigned char write_burst; + u16 bytes_to_transfer; /* the number of bytes to transfer */ + u8 read_burst; + u8 write_burst; - unsigned short actual_bytes_transferred;/* bytes transferred by DMA */ - unsigned char descriptor_status; - unsigned char descriptor_control; + u16 actual_bytes_transferred;/* bytes transferred by DMA */ + u8 descriptor_status; + u8 descriptor_control; } __packed_1_; /* SG-DMA Control/Status Slave registers map */ struct alt_sgdma_registers { - unsigned int status; - unsigned int status_pad[3]; - unsigned int control; - unsigned int control_pad[3]; - unsigned int next_descriptor_pointer; - unsigned int descriptor_pad[3]; + u32 status; + u32 status_pad[3]; + u32 control; + u32 control_pad[3]; + u32 next_descriptor_pointer; + u32 descriptor_pad[3]; }; /* TSE Stuff */ @@ -98,47 +98,47 @@ struct alt_sgdma_registers { /* MAC register Space */ struct alt_tse_mac { - unsigned int megacore_revision; - unsigned int scratch_pad; - unsigned int command_config; - unsigned int mac_addr_0; - unsigned int mac_addr_1; - unsigned int max_frame_length; - unsigned int pause_quanta; - unsigned int rx_sel_empty_threshold; - unsigned int rx_sel_full_threshold; - unsigned int tx_sel_empty_threshold; - unsigned int tx_sel_full_threshold; - unsigned int rx_almost_empty_threshold; - unsigned int rx_almost_full_threshold; - unsigned int tx_almost_empty_threshold; - unsigned int tx_almost_full_threshold; - unsigned int mdio_phy0_addr; - unsigned int mdio_phy1_addr; - - unsigned int reserved1[0x29]; + u32 megacore_revision; + u32 scratch_pad; + u32 command_config; + u32 mac_addr_0; + u32 mac_addr_1; + u32 max_frame_length; + u32 pause_quanta; + u32 rx_sel_empty_threshold; + u32 rx_sel_full_threshold; + u32 tx_sel_empty_threshold; + u32 tx_sel_full_threshold; + u32 rx_almost_empty_threshold; + u32 rx_almost_full_threshold; + u32 tx_almost_empty_threshold; + u32 tx_almost_full_threshold; + u32 mdio_phy0_addr; + u32 mdio_phy1_addr; + + u32 reserved1[0x29]; /*FIFO control register. */ - unsigned int tx_cmd_stat; - unsigned int rx_cmd_stat; + u32 tx_cmd_stat; + u32 rx_cmd_stat; - unsigned int reserved2[0x44]; + u32 reserved2[0x44]; /*Registers 0 to 31 within PHY device 0/1 */ - unsigned int mdio_phy0[0x20]; - unsigned int mdio_phy1[0x20]; + u32 mdio_phy0[0x20]; + u32 mdio_phy1[0x20]; /*4 Supplemental MAC Addresses */ - unsigned int supp_mac_addr_0_0; - unsigned int supp_mac_addr_0_1; - unsigned int supp_mac_addr_1_0; - unsigned int supp_mac_addr_1_1; - unsigned int supp_mac_addr_2_0; - unsigned int supp_mac_addr_2_1; - unsigned int supp_mac_addr_3_0; - unsigned int supp_mac_addr_3_1; - - unsigned int reserved3[0x38]; + u32 supp_mac_addr_0_0; + u32 supp_mac_addr_0_1; + u32 supp_mac_addr_1_0; + u32 supp_mac_addr_1_1; + u32 supp_mac_addr_2_0; + u32 supp_mac_addr_2_1; + u32 supp_mac_addr_3_0; + u32 supp_mac_addr_3_1; + + u32 reserved3[0x38]; }; struct altera_tse_priv { -- cgit v1.1 From 13146ec9380364c46dbc9473faff5707351935cc Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Fri, 6 Nov 2015 09:36:41 +0800 Subject: net: altera_tse: fix packed and aligned attribute Fix packed and aligned attribute warnings. WARNING: __packed is preferred over __attribute__((packed)) #14: FILE: drivers/net/altera_tse.h:14: +#define __packed_1_ __attribute__ ((packed, aligned(1))) WARNING: __aligned(size) is preferred over __attribute__((aligned(size))) #14: FILE: drivers/net/altera_tse.h:14: +#define __packed_1_ __attribute__ ((packed, aligned(1))) Signed-off-by: Thomas Chou Reviewed-by: Marek Vasut Reviewed-by: Chin Liang See Acked-by: Joe Hershberger --- drivers/net/altera_tse.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/altera_tse.h b/drivers/net/altera_tse.h index a96351a..78ae369 100644 --- a/drivers/net/altera_tse.h +++ b/drivers/net/altera_tse.h @@ -11,7 +11,7 @@ #ifndef _ALTERA_TSE_H_ #define _ALTERA_TSE_H_ -#define __packed_1_ __attribute__ ((packed, aligned(1))) +#define __packed_1_ __packed __aligned(1) /* SGDMA Stuff */ #define ALT_SGDMA_STATUS_BUSY_MSK (0x00000010) -- cgit v1.1 From 14fb5369909796f8de1a7fa0c8de1384d3dd2777 Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Fri, 6 Nov 2015 09:36:52 +0800 Subject: net: altera_tse: remove the useless parenthesis Remove the useless parenthesis. Signed-off-by: Thomas Chou Reviewed-by: Marek Vasut Reviewed-by: Chin Liang See Acked-by: Joe Hershberger --- drivers/net/altera_tse.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/altera_tse.h b/drivers/net/altera_tse.h index 78ae369..0981308 100644 --- a/drivers/net/altera_tse.h +++ b/drivers/net/altera_tse.h @@ -14,11 +14,11 @@ #define __packed_1_ __packed __aligned(1) /* SGDMA Stuff */ -#define ALT_SGDMA_STATUS_BUSY_MSK (0x00000010) +#define ALT_SGDMA_STATUS_BUSY_MSK 0x00000010 -#define ALT_SGDMA_CONTROL_RUN_MSK (0x00000020) -#define ALT_SGDMA_CONTROL_STOP_DMA_ER_MSK (0x00000040) -#define ALT_SGDMA_CONTROL_SOFTWARERESET_MSK (0x00010000) +#define ALT_SGDMA_CONTROL_RUN_MSK 0x00000020 +#define ALT_SGDMA_CONTROL_STOP_DMA_ER_MSK 0x00000040 +#define ALT_SGDMA_CONTROL_SOFTWARERESET_MSK 0x00010000 /* * Descriptor control bit masks & offsets @@ -27,10 +27,10 @@ * The following bit-offsets are expressed relative to the LSB of * the control register bitfield. */ -#define ALT_SGDMA_DESCRIPTOR_CONTROL_GENERATE_EOP_MSK (0x00000001) -#define ALT_SGDMA_DESCRIPTOR_CONTROL_READ_FIXED_ADDRESS_MSK (0x00000002) -#define ALT_SGDMA_DESCRIPTOR_CONTROL_WRITE_FIXED_ADDRESS_MSK (0x00000004) -#define ALT_SGDMA_DESCRIPTOR_CONTROL_OWNED_BY_HW_MSK (0x00000080) +#define ALT_SGDMA_DESCRIPTOR_CONTROL_GENERATE_EOP_MSK 0x00000001 +#define ALT_SGDMA_DESCRIPTOR_CONTROL_READ_FIXED_ADDRESS_MSK 0x00000002 +#define ALT_SGDMA_DESCRIPTOR_CONTROL_WRITE_FIXED_ADDRESS_MSK 0x00000004 +#define ALT_SGDMA_DESCRIPTOR_CONTROL_OWNED_BY_HW_MSK 0x00000080 /* * Descriptor status bit masks & offsets @@ -39,7 +39,7 @@ * The following bit-offsets are expressed relative to the LSB of * the status register bitfield. */ -#define ALT_SGDMA_DESCRIPTOR_STATUS_TERMINATED_BY_EOP_MSK (0x00000080) +#define ALT_SGDMA_DESCRIPTOR_STATUS_TERMINATED_BY_EOP_MSK 0x00000080 /* * The SGDMA controller buffer descriptor allocates @@ -85,12 +85,12 @@ struct alt_sgdma_registers { }; /* TSE Stuff */ -#define ALTERA_TSE_CMD_TX_ENA_MSK (0x00000001) -#define ALTERA_TSE_CMD_RX_ENA_MSK (0x00000002) -#define ALTERA_TSE_CMD_ETH_SPEED_MSK (0x00000008) -#define ALTERA_TSE_CMD_HD_ENA_MSK (0x00000400) -#define ALTERA_TSE_CMD_SW_RESET_MSK (0x00002000) -#define ALTERA_TSE_CMD_ENA_10_MSK (0x02000000) +#define ALTERA_TSE_CMD_TX_ENA_MSK 0x00000001 +#define ALTERA_TSE_CMD_RX_ENA_MSK 0x00000002 +#define ALTERA_TSE_CMD_ETH_SPEED_MSK 0x00000008 +#define ALTERA_TSE_CMD_HD_ENA_MSK 0x00000400 +#define ALTERA_TSE_CMD_SW_RESET_MSK 0x00002000 +#define ALTERA_TSE_CMD_ENA_10_MSK 0x02000000 #define ALT_TSE_SW_RESET_TIMEOUT (3 * CONFIG_SYS_HZ) #define ALT_TSE_SGDMA_BUSY_TIMEOUT (3 * CONFIG_SYS_HZ) -- cgit v1.1 From 4c8df1d359d0f40d6be272e46b0b12f83469a3c9 Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Fri, 6 Nov 2015 09:37:08 +0800 Subject: net: altera_tse: use BIT macro Replace numerical bit shift with BIT macro in altera_tse :%s/(1 << nr)/BIT(nr)/g where nr = 0, 1, 2 .... 31 Signed-off-by: Thomas Chou Reviewed-by: Marek Vasut Reviewed-by: Chin Liang See Reviewed-by: Jagan Teki Acked-by: Joe Hershberger --- drivers/net/altera_tse.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/altera_tse.h b/drivers/net/altera_tse.h index 0981308..471a880 100644 --- a/drivers/net/altera_tse.h +++ b/drivers/net/altera_tse.h @@ -14,11 +14,11 @@ #define __packed_1_ __packed __aligned(1) /* SGDMA Stuff */ -#define ALT_SGDMA_STATUS_BUSY_MSK 0x00000010 +#define ALT_SGDMA_STATUS_BUSY_MSK BIT(4) -#define ALT_SGDMA_CONTROL_RUN_MSK 0x00000020 -#define ALT_SGDMA_CONTROL_STOP_DMA_ER_MSK 0x00000040 -#define ALT_SGDMA_CONTROL_SOFTWARERESET_MSK 0x00010000 +#define ALT_SGDMA_CONTROL_RUN_MSK BIT(5) +#define ALT_SGDMA_CONTROL_STOP_DMA_ER_MSK BIT(6) +#define ALT_SGDMA_CONTROL_SOFTWARERESET_MSK BIT(16) /* * Descriptor control bit masks & offsets @@ -27,10 +27,10 @@ * The following bit-offsets are expressed relative to the LSB of * the control register bitfield. */ -#define ALT_SGDMA_DESCRIPTOR_CONTROL_GENERATE_EOP_MSK 0x00000001 -#define ALT_SGDMA_DESCRIPTOR_CONTROL_READ_FIXED_ADDRESS_MSK 0x00000002 -#define ALT_SGDMA_DESCRIPTOR_CONTROL_WRITE_FIXED_ADDRESS_MSK 0x00000004 -#define ALT_SGDMA_DESCRIPTOR_CONTROL_OWNED_BY_HW_MSK 0x00000080 +#define ALT_SGDMA_DESCRIPTOR_CONTROL_GENERATE_EOP_MSK BIT(0) +#define ALT_SGDMA_DESCRIPTOR_CONTROL_READ_FIXED_ADDRESS_MSK BIT(1) +#define ALT_SGDMA_DESCRIPTOR_CONTROL_WRITE_FIXED_ADDRESS_MSK BIT(2) +#define ALT_SGDMA_DESCRIPTOR_CONTROL_OWNED_BY_HW_MSK BIT(7) /* * Descriptor status bit masks & offsets @@ -39,7 +39,7 @@ * The following bit-offsets are expressed relative to the LSB of * the status register bitfield. */ -#define ALT_SGDMA_DESCRIPTOR_STATUS_TERMINATED_BY_EOP_MSK 0x00000080 +#define ALT_SGDMA_DESCRIPTOR_STATUS_TERMINATED_BY_EOP_MSK BIT(7) /* * The SGDMA controller buffer descriptor allocates @@ -85,12 +85,12 @@ struct alt_sgdma_registers { }; /* TSE Stuff */ -#define ALTERA_TSE_CMD_TX_ENA_MSK 0x00000001 -#define ALTERA_TSE_CMD_RX_ENA_MSK 0x00000002 -#define ALTERA_TSE_CMD_ETH_SPEED_MSK 0x00000008 -#define ALTERA_TSE_CMD_HD_ENA_MSK 0x00000400 -#define ALTERA_TSE_CMD_SW_RESET_MSK 0x00002000 -#define ALTERA_TSE_CMD_ENA_10_MSK 0x02000000 +#define ALTERA_TSE_CMD_TX_ENA_MSK BIT(0) +#define ALTERA_TSE_CMD_RX_ENA_MSK BIT(1) +#define ALTERA_TSE_CMD_ETH_SPEED_MSK BIT(3) +#define ALTERA_TSE_CMD_HD_ENA_MSK BIT(10) +#define ALTERA_TSE_CMD_SW_RESET_MSK BIT(13) +#define ALTERA_TSE_CMD_ENA_10_MSK BIT(25) #define ALT_TSE_SW_RESET_TIMEOUT (3 * CONFIG_SYS_HZ) #define ALT_TSE_SGDMA_BUSY_TIMEOUT (3 * CONFIG_SYS_HZ) -- cgit v1.1 From 75199d6f722a0f711628194240ee5bf724e31101 Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Fri, 6 Nov 2015 09:37:17 +0800 Subject: net: altera_tse: get numbers of fdt address and size cells Get numbers of fdt address and size cells in altera_tse_probe(), thereby remove the assumption of one address cell and one size cell. Signed-off-by: Thomas Chou Acked-by: Joe Hershberger --- drivers/net/altera_tse.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/altera_tse.c b/drivers/net/altera_tse.c index 394503f..b2002f4 100644 --- a/drivers/net/altera_tse.c +++ b/drivers/net/altera_tse.c @@ -409,20 +409,22 @@ static int altera_tse_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); struct altera_tse_priv *priv = dev_get_priv(dev); - const void *blob = gd->fdt_blob; + void *blob = (void *)gd->fdt_blob; int node = dev->of_offset; const char *list, *end; const fdt32_t *cell; void *base, *desc_mem = NULL; unsigned long addr, size; + int parent, addrc, sizec; int len, idx; int ret; /* - * decode regs, assume address-cells and size-cells are both one. - * there are multiple reg tuples, and they need to match with - * reg-names. + * decode regs. there are multiple reg tuples, and they need to + * match with reg-names. */ + parent = fdt_parent_offset(blob, node); + of_bus_default_count_cells(blob, parent, &addrc, &sizec); list = fdt_getprop(blob, node, "reg-names", &len); if (!list) return -ENOENT; @@ -434,7 +436,7 @@ static int altera_tse_probe(struct udevice *dev) while (list < end) { addr = fdt_translate_address((void *)blob, node, cell + idx); - size = fdt_addr_to_cpu(cell[idx + 1]); + size = fdt_addr_to_cpu(cell[idx + addrc]); base = ioremap(addr, size); len = strlen(list); if (strcmp(list, "control_port") == 0) @@ -445,7 +447,7 @@ static int altera_tse_probe(struct udevice *dev) priv->sgdma_tx = base; else if (strcmp(list, "s1") == 0) desc_mem = base; - idx += 2; + idx += addrc + sizec; list += (len + 1); } /* decode fifo depth */ -- cgit v1.1 From da58dec866161e8ce73957fea463a8caad695000 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Tue, 10 Nov 2015 01:06:16 +0000 Subject: Various Makefiles: Add SPDX-License-Identifier tags After consulting with some of the SPDX team, the conclusion is that Makefiles are worth adding SPDX-License-Identifier tags too, and most of ours have one. This adds tags to ones that lack them and converts a few that had full (or in one case, very partial) license blobs into the equivalent tag. Cc: Kate Stewart Signed-off-by: Tom Rini --- drivers/Makefile | 4 ++++ drivers/bios_emulator/Makefile | 4 ++++ drivers/ddr/fsl/Makefile | 4 +--- drivers/memory/Makefile | 2 ++ drivers/pinctrl/Makefile | 4 ++++ drivers/pinctrl/uniphier/Makefile | 4 ++++ drivers/soc/Makefile | 2 ++ drivers/soc/keystone/Makefile | 4 ++++ drivers/usb/dwc3/Makefile | 4 ++++ drivers/usb/gadget/udc/Makefile | 3 +++ drivers/usb/musb-new/Makefile | 2 ++ 11 files changed, 34 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/Makefile b/drivers/Makefile index ad29a4f..c9031f2 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + obj-$(CONFIG_$(SPL_)DM) += core/ obj-$(CONFIG_$(SPL_)CLK) += clk/ obj-$(CONFIG_$(SPL_)LED) += led/ diff --git a/drivers/bios_emulator/Makefile b/drivers/bios_emulator/Makefile index 2ba43ac..0a28074 100644 --- a/drivers/bios_emulator/Makefile +++ b/drivers/bios_emulator/Makefile @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + X86DIR = x86emu obj-y = atibios.o biosemu.o besys.o bios.o \ diff --git a/drivers/ddr/fsl/Makefile b/drivers/ddr/fsl/Makefile index df66c07..01ea862 100644 --- a/drivers/ddr/fsl/Makefile +++ b/drivers/ddr/fsl/Makefile @@ -1,9 +1,7 @@ # # Copyright 2008-2014 Freescale Semiconductor, Inc. # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# Version 2 as published by the Free Software Foundation. +# SPDX-License-Identifier: GPL-2.0 # obj-$(CONFIG_SYS_FSL_DDR1) += main.o util.o ctrl_regs.o options.o \ diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile index 9bfb9c7..6124e38 100644 --- a/drivers/memory/Makefile +++ b/drivers/memory/Makefile @@ -1 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0+ + obj-$(CONFIG_TI_AEMIF) += ti-aemif.o diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index e56a17f..70d25dc 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + obj-y += pinctrl-uclass.o obj-$(CONFIG_$(SPL_)PINCTRL_GENERIC) += pinctrl-generic.o diff --git a/drivers/pinctrl/uniphier/Makefile b/drivers/pinctrl/uniphier/Makefile index e215b10..c5cdd84 100644 --- a/drivers/pinctrl/uniphier/Makefile +++ b/drivers/pinctrl/uniphier/Makefile @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + obj-$(CONFIG_PINCTRL_UNIPHIER_CORE) += pinctrl-uniphier-core.o obj-$(CONFIG_PINCTRL_UNIPHIER_PH1_LD4) += pinctrl-ph1-ld4.o diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index 3d4baa5..99345eb 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -1,5 +1,7 @@ # # Makefile for the U-boot SOC specific device drivers. # +# SPDX-License-Identifier: GPL-2.0+ +# obj-$(CONFIG_ARCH_KEYSTONE) += keystone/ diff --git a/drivers/soc/keystone/Makefile b/drivers/soc/keystone/Makefile index c000eca..1334fa4 100644 --- a/drivers/soc/keystone/Makefile +++ b/drivers/soc/keystone/Makefile @@ -1 +1,5 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + obj-$(CONFIG_TI_KEYSTONE_SERDES) += keystone_serdes.o diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index 02bb216..0cd7302 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -1,3 +1,7 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + obj-$(CONFIG_USB_DWC3) += dwc3.o dwc3-y := core.o diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile index 12380f4..1699ccd 100644 --- a/drivers/usb/gadget/udc/Makefile +++ b/drivers/usb/gadget/udc/Makefile @@ -1,4 +1,7 @@ # # USB peripheral controller drivers # +# SPDX-License-Identifier: GPL-2.0+ +# + obj-$(CONFIG_USB_DWC3_GADGET) += udc-core.o diff --git a/drivers/usb/musb-new/Makefile b/drivers/usb/musb-new/Makefile index fd9df72..072d516 100644 --- a/drivers/usb/musb-new/Makefile +++ b/drivers/usb/musb-new/Makefile @@ -1,6 +1,8 @@ # # for USB OTG silicon based on Mentor Graphics INVENTRA designs # +# SPDX-License-Identifier: GPL-2.0+ +# obj-$(CONFIG_USB_MUSB_GADGET) += musb_gadget.o musb_gadget_ep0.o musb_core.o obj-$(CONFIG_USB_MUSB_GADGET) += musb_uboot.o -- cgit v1.1 From d85879938d3fc3557f6ff74a60f95e0975a314ce Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Sat, 7 Nov 2015 14:20:31 +0800 Subject: dm: implement a MTD uclass Implement a Memory Technology Device (MTD) uclass. It should include most flash drivers in the future. Though no uclass ops are defined yet, the MTD ops could be used. The NAND flash driver is based on MTD. The CFI flash and SPI flash support MTD, too. It should make sense to convert them to MTD uclass. Signed-off-by: Thomas Chou --- drivers/mtd/Kconfig | 12 ++++++++++++ drivers/mtd/Makefile | 1 + drivers/mtd/mtd-uclass.c | 21 +++++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 drivers/mtd/mtd-uclass.c (limited to 'drivers') diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 59278d1..23dff48 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -1,3 +1,15 @@ +menu "MTD Support" + +config MTD + bool "Enable Driver Model for MTD drivers" + depends on DM + help + Enable driver model for Memory Technology Devices (MTD), such as + flash, RAM and similar chips, often used for solid state file + systems on embedded devices. + +endmenu + source "drivers/mtd/nand/Kconfig" source "drivers/mtd/spi/Kconfig" diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index a623f4c..c23c0c1 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -8,6 +8,7 @@ ifneq (,$(findstring y,$(CONFIG_MTD_DEVICE)$(CONFIG_CMD_NAND)$(CONFIG_CMD_ONENAND)$(CONFIG_CMD_SF))) obj-y += mtdcore.o mtd_uboot.o endif +obj-$(CONFIG_MTD) += mtd-uclass.o obj-$(CONFIG_MTD_PARTITIONS) += mtdpart.o obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o obj-$(CONFIG_HAS_DATAFLASH) += at45.o diff --git a/drivers/mtd/mtd-uclass.c b/drivers/mtd/mtd-uclass.c new file mode 100644 index 0000000..7b7c48e --- /dev/null +++ b/drivers/mtd/mtd-uclass.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2015 Thomas Chou + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +/* + * Implement a MTD uclass which should include most flash drivers. + * The uclass private is pointed to mtd_info. + */ + +UCLASS_DRIVER(mtd) = { + .id = UCLASS_MTD, + .name = "mtd", + .per_device_auto_alloc_size = sizeof(struct mtd_info), +}; -- cgit v1.1 From f1056910434d87051ff8af80a84e248dd1670abb Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Sat, 7 Nov 2015 14:31:08 +0800 Subject: cfi_flash: convert to driver model Convert cfi flash to driver model. Signed-off-by: Thomas Chou Reviewed-by: Simon Glass --- drivers/mtd/Kconfig | 11 +++++++ drivers/mtd/cfi_flash.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) (limited to 'drivers') diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 23dff48..57e4b86 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -8,6 +8,17 @@ config MTD flash, RAM and similar chips, often used for solid state file systems on embedded devices. +config CFI_FLASH + bool "Enable Driver Model for CFI Flash driver" + depends on MTD + help + The Common Flash Interface specification was developed by Intel, + AMD and other flash manufactures. It provides a universal method + for probing the capabilities of flash devices. If you wish to + support any device that is CFI-compliant, you need to enable this + option. Visit + for more information on CFI. + endmenu source "drivers/mtd/nand/Kconfig" diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c index fc7a878..e3cb598 100644 --- a/drivers/mtd/cfi_flash.c +++ b/drivers/mtd/cfi_flash.c @@ -18,6 +18,9 @@ /* #define DEBUG */ #include +#include +#include +#include #include #include #include @@ -47,6 +50,8 @@ * reading and writing ... (yes there is such a Hardware). */ +DECLARE_GLOBAL_DATA_PTR; + static uint flash_offset_cfi[2] = { FLASH_OFFSET_CFI, FLASH_OFFSET_CFI_ALT }; #ifdef CONFIG_FLASH_CFI_MTD static uint flash_verbose = 1; @@ -87,10 +92,36 @@ static u16 cfi_flash_config_reg(int i) int cfi_flash_num_flash_banks = CONFIG_SYS_MAX_FLASH_BANKS_DETECT; #endif +#ifdef CONFIG_CFI_FLASH /* for driver model */ +static void cfi_flash_init_dm(void) +{ + struct udevice *dev; + + cfi_flash_num_flash_banks = 0; + /* + * The uclass_first_device() will probe the first device and + * uclass_next_device() will probe the rest if they exist. So + * that cfi_flash_probe() will get called assigning the base + * addresses that are available. + */ + for (uclass_first_device(UCLASS_MTD, &dev); + dev; + uclass_next_device(&dev)) { + } +} + +static phys_addr_t cfi_flash_base[CFI_MAX_FLASH_BANKS]; + +phys_addr_t cfi_flash_bank_addr(int i) +{ + return cfi_flash_base[i]; +} +#else __weak phys_addr_t cfi_flash_bank_addr(int i) { return ((phys_addr_t [])CONFIG_SYS_FLASH_BANKS_LIST)[i]; } +#endif __weak unsigned long cfi_flash_bank_size(int i) { @@ -2322,6 +2353,10 @@ unsigned long flash_init (void) getenv_f("unlock", s, sizeof(s)); #endif +#ifdef CONFIG_CFI_FLASH /* for driver model */ + cfi_flash_init_dm(); +#endif + /* Init: no FLASHes known */ for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) { flash_info[i].flash_id = FLASH_UNKNOWN; @@ -2398,3 +2433,46 @@ unsigned long flash_init (void) return (size); } + +#ifdef CONFIG_CFI_FLASH /* for driver model */ +static int cfi_flash_probe(struct udevice *dev) +{ + void *blob = (void *)gd->fdt_blob; + int node = dev->of_offset; + const fdt32_t *cell; + phys_addr_t addr; + int parent, addrc, sizec; + int len, idx; + + parent = fdt_parent_offset(blob, node); + of_bus_default_count_cells(blob, parent, &addrc, &sizec); + /* decode regs, there may be multiple reg tuples. */ + cell = fdt_getprop(blob, node, "reg", &len); + if (!cell) + return -ENOENT; + idx = 0; + len /= sizeof(fdt32_t); + while (idx < len) { + addr = fdt_translate_address((void *)blob, + node, cell + idx); + cfi_flash_base[cfi_flash_num_flash_banks++] = addr; + idx += addrc + sizec; + } + gd->bd->bi_flashstart = cfi_flash_base[0]; + + return 0; +} + +static const struct udevice_id cfi_flash_ids[] = { + { .compatible = "cfi-flash" }, + { .compatible = "jedec-flash" }, + {} +}; + +U_BOOT_DRIVER(cfi_flash) = { + .name = "cfi_flash", + .id = UCLASS_MTD, + .of_match = cfi_flash_ids, + .probe = cfi_flash_probe, +}; +#endif /* CONFIG_CFI_FLASH */ -- cgit v1.1 From 38a0f36e83e1d707eceab3c31da65a22c8140bb3 Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Mon, 9 Nov 2015 14:56:02 +0800 Subject: mtd: add altera quadspi driver Add Altera Generic Quad SPI Controller support. The controller converts SPI NOR flash to parallel flash interface. So it is not like other SPI flash, but rather like CFI flash. Signed-off-by: Thomas Chou --- drivers/mtd/Kconfig | 9 ++ drivers/mtd/Makefile | 1 + drivers/mtd/altera_qspi.c | 273 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 283 insertions(+) create mode 100644 drivers/mtd/altera_qspi.c (limited to 'drivers') diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 57e4b86..c58841e 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -19,6 +19,15 @@ config CFI_FLASH option. Visit for more information on CFI. +config ALTERA_QSPI + bool "Altera Generic Quad SPI Controller" + depends on MTD + help + This enables access to Altera EPCQ/EPCS flash chips using the + Altera Generic Quad SPI Controller. The controller converts SPI + NOR flash to parallel flash interface. Please find details on the + "Embedded Peripherals IP User Guide" of Altera. + endmenu source "drivers/mtd/nand/Kconfig" diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index c23c0c1..7f018a4 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -11,6 +11,7 @@ endif obj-$(CONFIG_MTD) += mtd-uclass.o obj-$(CONFIG_MTD_PARTITIONS) += mtdpart.o obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o +obj-$(CONFIG_ALTERA_QSPI) += altera_qspi.o obj-$(CONFIG_HAS_DATAFLASH) += at45.o obj-$(CONFIG_FLASH_CFI_DRIVER) += cfi_flash.o obj-$(CONFIG_FLASH_CFI_MTD) += cfi_mtd.o diff --git a/drivers/mtd/altera_qspi.c b/drivers/mtd/altera_qspi.c new file mode 100644 index 0000000..1826dc8 --- /dev/null +++ b/drivers/mtd/altera_qspi.c @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2015 Thomas Chou + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* + * The QUADSPI_MEM_OP register is used to do memory protect and erase operations + */ +#define QUADSPI_MEM_OP_BULK_ERASE 0x00000001 +#define QUADSPI_MEM_OP_SECTOR_ERASE 0x00000002 +#define QUADSPI_MEM_OP_SECTOR_PROTECT 0x00000003 + +/* + * The QUADSPI_ISR register is used to determine whether an invalid write or + * erase operation trigerred an interrupt + */ +#define QUADSPI_ISR_ILLEGAL_ERASE BIT(0) +#define QUADSPI_ISR_ILLEGAL_WRITE BIT(1) + +struct altera_qspi_regs { + u32 rd_status; + u32 rd_sid; + u32 rd_rdid; + u32 mem_op; + u32 isr; + u32 imr; + u32 chip_select; +}; + +struct altera_qspi_platdata { + struct altera_qspi_regs *regs; + void *base; + unsigned long size; +}; + +flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* FLASH chips info */ + +void flash_print_info(flash_info_t *info) +{ + printf("Altera QSPI flash Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); +} + +int flash_erase(flash_info_t *info, int s_first, int s_last) +{ + struct mtd_info *mtd = info->mtd; + struct erase_info instr; + int ret; + + memset(&instr, 0, sizeof(instr)); + instr.addr = mtd->erasesize * s_first; + instr.len = mtd->erasesize * (s_last + 1 - s_first); + ret = mtd_erase(mtd, &instr); + if (ret) + return ERR_NOT_ERASED; + + return 0; +} + +int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + struct mtd_info *mtd = info->mtd; + struct udevice *dev = mtd->dev; + struct altera_qspi_platdata *pdata = dev_get_platdata(dev); + ulong base = (ulong)pdata->base; + loff_t to = addr - base; + size_t retlen; + int ret; + + ret = mtd_write(mtd, to, cnt, &retlen, src); + if (ret) + return ERR_NOT_ERASED; + + return 0; +} + +unsigned long flash_init(void) +{ + struct udevice *dev; + + /* probe every MTD device */ + for (uclass_first_device(UCLASS_MTD, &dev); + dev; + uclass_next_device(&dev)) { + } + + return flash_info[0].size; +} + +static int altera_qspi_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + struct udevice *dev = mtd->dev; + struct altera_qspi_platdata *pdata = dev_get_platdata(dev); + struct altera_qspi_regs *regs = pdata->regs; + size_t addr = instr->addr; + size_t len = instr->len; + size_t end = addr + len; + u32 sect; + u32 stat; + + instr->state = MTD_ERASING; + addr &= ~(mtd->erasesize - 1); /* get lower aligned address */ + while (addr < end) { + sect = addr / mtd->erasesize; + sect <<= 8; + sect |= QUADSPI_MEM_OP_SECTOR_ERASE; + debug("erase %08x\n", sect); + writel(sect, ®s->mem_op); + stat = readl(®s->isr); + if (stat & QUADSPI_ISR_ILLEGAL_ERASE) { + /* erase failed, sector might be protected */ + debug("erase %08x fail %x\n", sect, stat); + writel(stat, ®s->isr); /* clear isr */ + instr->state = MTD_ERASE_FAILED; + return -EIO; + } + addr += mtd->erasesize; + } + instr->state = MTD_ERASE_DONE; + mtd_erase_callback(instr); + + return 0; +} + +static int altera_qspi_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct udevice *dev = mtd->dev; + struct altera_qspi_platdata *pdata = dev_get_platdata(dev); + + memcpy_fromio(buf, pdata->base + from, len); + *retlen = len; + + return 0; +} + +static int altera_qspi_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + struct udevice *dev = mtd->dev; + struct altera_qspi_platdata *pdata = dev_get_platdata(dev); + struct altera_qspi_regs *regs = pdata->regs; + u32 stat; + + memcpy_toio(pdata->base + to, buf, len); + /* check whether write triggered a illegal write interrupt */ + stat = readl(®s->isr); + if (stat & QUADSPI_ISR_ILLEGAL_WRITE) { + /* write failed, sector might be protected */ + debug("write fail %x\n", stat); + writel(stat, ®s->isr); /* clear isr */ + return -EIO; + } + *retlen = len; + + return 0; +} + +static void altera_qspi_sync(struct mtd_info *mtd) +{ +} + +static int altera_qspi_probe(struct udevice *dev) +{ + struct altera_qspi_platdata *pdata = dev_get_platdata(dev); + struct altera_qspi_regs *regs = pdata->regs; + unsigned long base = (unsigned long)pdata->base; + struct mtd_info *mtd; + flash_info_t *flash = &flash_info[0]; + u32 rdid; + int i; + + rdid = readl(®s->rd_rdid); + debug("rdid %x\n", rdid); + + mtd = dev_get_uclass_priv(dev); + mtd->dev = dev; + mtd->name = "nor0"; + mtd->type = MTD_NORFLASH; + mtd->flags = MTD_CAP_NORFLASH; + mtd->size = 1 << ((rdid & 0xff) - 6); + mtd->writesize = 1; + mtd->writebufsize = mtd->writesize; + mtd->_erase = altera_qspi_erase; + mtd->_read = altera_qspi_read; + mtd->_write = altera_qspi_write; + mtd->_sync = altera_qspi_sync; + mtd->numeraseregions = 0; + mtd->erasesize = 0x10000; + if (add_mtd_device(mtd)) + return -ENOMEM; + + flash->mtd = mtd; + flash->size = mtd->size; + flash->sector_count = mtd->size / mtd->erasesize; + flash->flash_id = rdid; + flash->start[0] = base; + for (i = 1; i < flash->sector_count; i++) + flash->start[i] = flash->start[i - 1] + mtd->erasesize; + gd->bd->bi_flashstart = base; + + return 0; +} + +static int altera_qspi_ofdata_to_platdata(struct udevice *dev) +{ + struct altera_qspi_platdata *pdata = dev_get_platdata(dev); + void *blob = (void *)gd->fdt_blob; + int node = dev->of_offset; + const char *list, *end; + const fdt32_t *cell; + void *base; + unsigned long addr, size; + int parent, addrc, sizec; + int len, idx; + + /* + * decode regs. there are multiple reg tuples, and they need to + * match with reg-names. + */ + parent = fdt_parent_offset(blob, node); + of_bus_default_count_cells(blob, parent, &addrc, &sizec); + list = fdt_getprop(blob, node, "reg-names", &len); + if (!list) + return -ENOENT; + end = list + len; + cell = fdt_getprop(blob, node, "reg", &len); + if (!cell) + return -ENOENT; + idx = 0; + while (list < end) { + addr = fdt_translate_address((void *)blob, + node, cell + idx); + size = fdt_addr_to_cpu(cell[idx + addrc]); + base = ioremap(addr, size); + len = strlen(list); + if (strcmp(list, "avl_csr") == 0) { + pdata->regs = base; + } else if (strcmp(list, "avl_mem") == 0) { + pdata->base = base; + pdata->size = size; + } + idx += addrc + sizec; + list += (len + 1); + } + + return 0; +} + +static const struct udevice_id altera_qspi_ids[] = { + { .compatible = "altr,quadspi-1.0" }, + {} +}; + +U_BOOT_DRIVER(altera_qspi) = { + .name = "altera_qspi", + .id = UCLASS_MTD, + .of_match = altera_qspi_ids, + .ofdata_to_platdata = altera_qspi_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct altera_qspi_platdata), + .probe = altera_qspi_probe, +}; -- cgit v1.1 From acd71c320f917fbd3a2c4978117a2b586e245f42 Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Sun, 8 Nov 2015 10:57:05 +0800 Subject: net: altera_tse: factor out stop mac func Factor out the stop mac function to prepare msgdma support. Signed-off-by: Thomas Chou Reviewed-by: Marek Vasut --- drivers/net/altera_tse.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/altera_tse.c b/drivers/net/altera_tse.c index b2002f4..fe8c524 100644 --- a/drivers/net/altera_tse.c +++ b/drivers/net/altera_tse.c @@ -223,16 +223,33 @@ static int altera_tse_free_pkt(struct udevice *dev, uchar *packet, return 0; } +static void altera_tse_stop_mac(struct altera_tse_priv *priv) +{ + struct alt_tse_mac *mac_dev = priv->mac_dev; + u32 status; + ulong ctime; + + /* reset the mac */ + writel(ALTERA_TSE_CMD_SW_RESET_MSK, &mac_dev->command_config); + ctime = get_timer(0); + while (1) { + status = readl(&mac_dev->command_config); + if (!(status & ALTERA_TSE_CMD_SW_RESET_MSK)) + break; + if (get_timer(ctime) > ALT_TSE_SW_RESET_TIMEOUT) { + debug("Reset mac timeout\n"); + break; + } + } +} + static void altera_tse_stop(struct udevice *dev) { struct altera_tse_priv *priv = dev_get_priv(dev); - struct alt_tse_mac *mac_dev = priv->mac_dev; struct alt_sgdma_registers *rx_sgdma = priv->sgdma_rx; struct alt_sgdma_registers *tx_sgdma = priv->sgdma_tx; struct alt_sgdma_descriptor *rx_desc = priv->rx_desc; - u32 status; int ret; - ulong ctime; /* clear rx desc & wait for sgdma to complete */ rx_desc->descriptor_control = 0; @@ -248,18 +265,7 @@ static void altera_tse_stop(struct udevice *dev) writel(ALT_SGDMA_CONTROL_SOFTWARERESET_MSK, &tx_sgdma->control); - /* reset the mac */ - writel(ALTERA_TSE_CMD_SW_RESET_MSK, &mac_dev->command_config); - ctime = get_timer(0); - while (1) { - status = readl(&mac_dev->command_config); - if (!(status & ALTERA_TSE_CMD_SW_RESET_MSK)) - break; - if (get_timer(ctime) > ALT_TSE_SW_RESET_TIMEOUT) { - debug("Reset mac timeout\n"); - break; - } - } + altera_tse_stop_mac(priv); } static int tse_mdio_read(struct mii_dev *bus, int addr, int devad, int reg) -- cgit v1.1 From 577662f0845d5fa701261879c7d18c8073cf9e7d Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Mon, 9 Nov 2015 08:00:00 +0800 Subject: net: altera_tse: wait sgdma in altera_tse_recv Move the sgdma wait from free_pkt to recv. This is the proper place to wait recv sgdma done. Signed-off-by: Thomas Chou Reviewed-by: Marek Vasut --- drivers/net/altera_tse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/altera_tse.c b/drivers/net/altera_tse.c index fe8c524..8ec0beb 100644 --- a/drivers/net/altera_tse.c +++ b/drivers/net/altera_tse.c @@ -186,6 +186,7 @@ static int altera_tse_recv(struct udevice *dev, int flags, uchar **packetp) if (rx_desc->descriptor_status & ALT_SGDMA_DESCRIPTOR_STATUS_TERMINATED_BY_EOP_MSK) { + alt_sgdma_wait_transfer(priv->sgdma_rx); packet_length = rx_desc->actual_bytes_transferred; debug("recv %d bytes\n", packet_length); *packetp = priv->rx_buf; @@ -203,7 +204,6 @@ static int altera_tse_free_pkt(struct udevice *dev, uchar *packet, struct alt_sgdma_descriptor *rx_desc = priv->rx_desc; unsigned long rx_buf = (unsigned long)priv->rx_buf; - alt_sgdma_wait_transfer(priv->sgdma_rx); invalidate_dcache_range(rx_buf, rx_buf + PKTSIZE_ALIGN); alt_sgdma_construct_descriptor( rx_desc, -- cgit v1.1 From 38fa4aca8a70b71edab2d4df473253d9c4582f39 Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Mon, 9 Nov 2015 11:02:15 +0800 Subject: net: altera_tse: add priv ops to prepare msgdma support Add priv ops to prepare msgdma support. These ops are dma type specific. Signed-off-by: Thomas Chou Reviewed-by: Marek Vasut --- drivers/net/altera_tse.c | 86 ++++++++++++++++++++++++++++++++++++------------ drivers/net/altera_tse.h | 20 ++++++++--- 2 files changed, 81 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/net/altera_tse.c b/drivers/net/altera_tse.c index 8ec0beb..3848530 100644 --- a/drivers/net/altera_tse.c +++ b/drivers/net/altera_tse.c @@ -152,13 +152,11 @@ static void tse_adjust_link(struct altera_tse_priv *priv, writel(refvar, &mac_dev->command_config); } -static int altera_tse_send(struct udevice *dev, void *packet, int length) +static int altera_tse_send_sgdma(struct udevice *dev, void *packet, int length) { struct altera_tse_priv *priv = dev_get_priv(dev); struct alt_sgdma_descriptor *tx_desc = priv->tx_desc; - unsigned long tx_buf = (unsigned long)packet; - flush_dcache_range(tx_buf, tx_buf + length); alt_sgdma_construct_descriptor( tx_desc, tx_desc + 1, @@ -178,7 +176,8 @@ static int altera_tse_send(struct udevice *dev, void *packet, int length) return tx_desc->actual_bytes_transferred; } -static int altera_tse_recv(struct udevice *dev, int flags, uchar **packetp) +static int altera_tse_recv_sgdma(struct udevice *dev, int flags, + uchar **packetp) { struct altera_tse_priv *priv = dev_get_priv(dev); struct alt_sgdma_descriptor *rx_desc = priv->rx_desc; @@ -197,14 +196,12 @@ static int altera_tse_recv(struct udevice *dev, int flags, uchar **packetp) return -EAGAIN; } -static int altera_tse_free_pkt(struct udevice *dev, uchar *packet, - int length) +static int altera_tse_free_pkt_sgdma(struct udevice *dev, uchar *packet, + int length) { struct altera_tse_priv *priv = dev_get_priv(dev); struct alt_sgdma_descriptor *rx_desc = priv->rx_desc; - unsigned long rx_buf = (unsigned long)priv->rx_buf; - invalidate_dcache_range(rx_buf, rx_buf + PKTSIZE_ALIGN); alt_sgdma_construct_descriptor( rx_desc, rx_desc + 1, @@ -243,7 +240,7 @@ static void altera_tse_stop_mac(struct altera_tse_priv *priv) } } -static void altera_tse_stop(struct udevice *dev) +static void altera_tse_stop_sgdma(struct udevice *dev) { struct altera_tse_priv *priv = dev_get_priv(dev); struct alt_sgdma_registers *rx_sgdma = priv->sgdma_rx; @@ -264,8 +261,6 @@ static void altera_tse_stop(struct udevice *dev) if (ret == -ETIMEDOUT) writel(ALT_SGDMA_CONTROL_SOFTWARERESET_MSK, &tx_sgdma->control); - - altera_tse_stop_mac(priv); } static int tse_mdio_read(struct mii_dev *bus, int addr, int devad, int reg) @@ -364,6 +359,42 @@ static int altera_tse_write_hwaddr(struct udevice *dev) return 0; } +static int altera_tse_send(struct udevice *dev, void *packet, int length) +{ + struct altera_tse_priv *priv = dev_get_priv(dev); + unsigned long tx_buf = (unsigned long)packet; + + flush_dcache_range(tx_buf, tx_buf + length); + + return priv->ops->send(dev, packet, length); +} + +static int altera_tse_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct altera_tse_priv *priv = dev_get_priv(dev); + + return priv->ops->recv(dev, flags, packetp); +} + +static int altera_tse_free_pkt(struct udevice *dev, uchar *packet, + int length) +{ + struct altera_tse_priv *priv = dev_get_priv(dev); + unsigned long rx_buf = (unsigned long)priv->rx_buf; + + invalidate_dcache_range(rx_buf, rx_buf + PKTSIZE_ALIGN); + + return priv->ops->free_pkt(dev, packet, length); +} + +static void altera_tse_stop(struct udevice *dev) +{ + struct altera_tse_priv *priv = dev_get_priv(dev); + + priv->ops->stop(dev); + altera_tse_stop_mac(priv); +} + static int altera_tse_start(struct udevice *dev) { struct altera_tse_priv *priv = dev_get_priv(dev); @@ -411,6 +442,13 @@ static int altera_tse_start(struct udevice *dev) return 0; } +static const struct tse_ops tse_sgdma_ops = { + .send = altera_tse_send_sgdma, + .recv = altera_tse_recv_sgdma, + .free_pkt = altera_tse_free_pkt_sgdma, + .stop = altera_tse_stop_sgdma, +}; + static int altera_tse_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); @@ -425,6 +463,9 @@ static int altera_tse_probe(struct udevice *dev) int len, idx; int ret; + priv->dma_type = dev_get_driver_data(dev); + if (priv->dma_type == ALT_SGDMA) + priv->ops = &tse_sgdma_ops; /* * decode regs. there are multiple reg tuples, and they need to * match with reg-names. @@ -468,15 +509,18 @@ static int altera_tse_probe(struct udevice *dev) priv->phyaddr = fdtdec_get_int(blob, addr, "reg", 0); /* init desc */ - len = sizeof(struct alt_sgdma_descriptor) * 4; - if (!desc_mem) { - desc_mem = dma_alloc_coherent(len, &addr); - if (!desc_mem) - return -ENOMEM; + if (priv->dma_type == ALT_SGDMA) { + len = sizeof(struct alt_sgdma_descriptor) * 4; + if (!desc_mem) { + desc_mem = dma_alloc_coherent(len, &addr); + if (!desc_mem) + return -ENOMEM; + } + memset(desc_mem, 0, len); + priv->tx_desc = desc_mem; + priv->rx_desc = priv->tx_desc + + 2 * sizeof(struct alt_sgdma_descriptor); } - memset(desc_mem, 0, len); - priv->tx_desc = desc_mem; - priv->rx_desc = priv->tx_desc + 2; /* allocate recv packet buffer */ priv->rx_buf = malloc_cache_aligned(PKTSIZE_ALIGN); if (!priv->rx_buf) @@ -523,8 +567,8 @@ static const struct eth_ops altera_tse_ops = { }; static const struct udevice_id altera_tse_ids[] = { - { .compatible = "altr,tse-1.0", }, - { } + { .compatible = "altr,tse-1.0", .data = ALT_SGDMA }, + {} }; U_BOOT_DRIVER(altera_tse) = { diff --git a/drivers/net/altera_tse.h b/drivers/net/altera_tse.h index 471a880..fae2378 100644 --- a/drivers/net/altera_tse.h +++ b/drivers/net/altera_tse.h @@ -13,6 +13,9 @@ #define __packed_1_ __packed __aligned(1) +/* dma type */ +#define ALT_SGDMA 0 + /* SGDMA Stuff */ #define ALT_SGDMA_STATUS_BUSY_MSK BIT(4) @@ -141,19 +144,28 @@ struct alt_tse_mac { u32 reserved3[0x38]; }; +struct tse_ops { + int (*send)(struct udevice *dev, void *packet, int length); + int (*recv)(struct udevice *dev, int flags, uchar **packetp); + int (*free_pkt)(struct udevice *dev, uchar *packet, int length); + void (*stop)(struct udevice *dev); +}; + struct altera_tse_priv { struct alt_tse_mac *mac_dev; - struct alt_sgdma_registers *sgdma_rx; - struct alt_sgdma_registers *sgdma_tx; + void *sgdma_rx; + void *sgdma_tx; unsigned int rx_fifo_depth; unsigned int tx_fifo_depth; - struct alt_sgdma_descriptor *rx_desc; - struct alt_sgdma_descriptor *tx_desc; + void *rx_desc; + void *tx_desc; unsigned char *rx_buf; unsigned int phyaddr; unsigned int interface; struct phy_device *phydev; struct mii_dev *bus; + const struct tse_ops *ops; + int dma_type; }; #endif /* _ALTERA_TSE_H_ */ -- cgit v1.1 From e3e872604df60ac1c3c8568ad037ab47e788ec10 Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Mon, 9 Nov 2015 14:36:29 +0800 Subject: net: altera_tse: add mSG-DMA support The Modular Scatter-Gather DMA core is a new DMA core to work with the Altera Triple-Speed Ethernet MegaCore. It replaces the legacy Scatter-Gather Direct Memory Access (SG-DMA) controller core. Please find details on the "Embedded Peripherals IP User Guide" of Altera. Signed-off-by: Thomas Chou Reviewed-by: Marek Vasut --- drivers/net/altera_tse.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/altera_tse.h | 60 ++++++++++++++++++++++ 2 files changed, 191 insertions(+) (limited to 'drivers') diff --git a/drivers/net/altera_tse.c b/drivers/net/altera_tse.c index 3848530..5692fe9 100644 --- a/drivers/net/altera_tse.c +++ b/drivers/net/altera_tse.c @@ -263,6 +263,121 @@ static void altera_tse_stop_sgdma(struct udevice *dev) &tx_sgdma->control); } +static void msgdma_reset(struct msgdma_csr *csr) +{ + u32 status; + ulong ctime; + + /* Reset mSGDMA */ + writel(MSGDMA_CSR_STAT_MASK, &csr->status); + writel(MSGDMA_CSR_CTL_RESET, &csr->control); + ctime = get_timer(0); + while (1) { + status = readl(&csr->status); + if (!(status & MSGDMA_CSR_STAT_RESETTING)) + break; + if (get_timer(ctime) > ALT_TSE_SW_RESET_TIMEOUT) { + debug("Reset msgdma timeout\n"); + break; + } + } + /* Clear status */ + writel(MSGDMA_CSR_STAT_MASK, &csr->status); +} + +static u32 msgdma_wait(struct msgdma_csr *csr) +{ + u32 status; + ulong ctime; + + /* Wait for the descriptor to complete */ + ctime = get_timer(0); + while (1) { + status = readl(&csr->status); + if (!(status & MSGDMA_CSR_STAT_BUSY)) + break; + if (get_timer(ctime) > ALT_TSE_SGDMA_BUSY_TIMEOUT) { + debug("sgdma timeout\n"); + break; + } + } + /* Clear status */ + writel(MSGDMA_CSR_STAT_MASK, &csr->status); + + return status; +} + +static int altera_tse_send_msgdma(struct udevice *dev, void *packet, + int length) +{ + struct altera_tse_priv *priv = dev_get_priv(dev); + struct msgdma_extended_desc *desc = priv->tx_desc; + u32 tx_buf = virt_to_phys(packet); + u32 status; + + writel(tx_buf, &desc->read_addr_lo); + writel(0, &desc->read_addr_hi); + writel(0, &desc->write_addr_lo); + writel(0, &desc->write_addr_hi); + writel(length, &desc->len); + writel(0, &desc->burst_seq_num); + writel(MSGDMA_DESC_TX_STRIDE, &desc->stride); + writel(MSGDMA_DESC_CTL_TX_SINGLE, &desc->control); + status = msgdma_wait(priv->sgdma_tx); + debug("sent %d bytes, status %08x\n", length, status); + + return 0; +} + +static int altera_tse_recv_msgdma(struct udevice *dev, int flags, + uchar **packetp) +{ + struct altera_tse_priv *priv = dev_get_priv(dev); + struct msgdma_csr *csr = priv->sgdma_rx; + struct msgdma_response *resp = priv->rx_resp; + u32 level, length, status; + + level = readl(&csr->resp_fill_level); + if (level & 0xffff) { + length = readl(&resp->bytes_transferred); + status = readl(&resp->status); + debug("recv %d bytes, status %08x\n", length, status); + *packetp = priv->rx_buf; + + return length; + } + + return -EAGAIN; +} + +static int altera_tse_free_pkt_msgdma(struct udevice *dev, uchar *packet, + int length) +{ + struct altera_tse_priv *priv = dev_get_priv(dev); + struct msgdma_extended_desc *desc = priv->rx_desc; + u32 rx_buf = virt_to_phys(priv->rx_buf); + + writel(0, &desc->read_addr_lo); + writel(0, &desc->read_addr_hi); + writel(rx_buf, &desc->write_addr_lo); + writel(0, &desc->write_addr_hi); + writel(PKTSIZE_ALIGN, &desc->len); + writel(0, &desc->burst_seq_num); + writel(MSGDMA_DESC_RX_STRIDE, &desc->stride); + writel(MSGDMA_DESC_CTL_RX_SINGLE, &desc->control); + debug("recv setup\n"); + + return 0; +} + +static void altera_tse_stop_msgdma(struct udevice *dev) +{ + struct altera_tse_priv *priv = dev_get_priv(dev); + + msgdma_reset(priv->sgdma_rx); + msgdma_reset(priv->sgdma_tx); +} + static int tse_mdio_read(struct mii_dev *bus, int addr, int devad, int reg) { struct altera_tse_priv *priv = bus->priv; @@ -449,6 +564,13 @@ static const struct tse_ops tse_sgdma_ops = { .stop = altera_tse_stop_sgdma, }; +static const struct tse_ops tse_msgdma_ops = { + .send = altera_tse_send_msgdma, + .recv = altera_tse_recv_msgdma, + .free_pkt = altera_tse_free_pkt_msgdma, + .stop = altera_tse_stop_msgdma, +}; + static int altera_tse_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); @@ -466,6 +588,8 @@ static int altera_tse_probe(struct udevice *dev) priv->dma_type = dev_get_driver_data(dev); if (priv->dma_type == ALT_SGDMA) priv->ops = &tse_sgdma_ops; + else + priv->ops = &tse_msgdma_ops; /* * decode regs. there are multiple reg tuples, and they need to * match with reg-names. @@ -490,8 +614,14 @@ static int altera_tse_probe(struct udevice *dev) priv->mac_dev = base; else if (strcmp(list, "rx_csr") == 0) priv->sgdma_rx = base; + else if (strcmp(list, "rx_desc") == 0) + priv->rx_desc = base; + else if (strcmp(list, "rx_resp") == 0) + priv->rx_resp = base; else if (strcmp(list, "tx_csr") == 0) priv->sgdma_tx = base; + else if (strcmp(list, "tx_desc") == 0) + priv->tx_desc = base; else if (strcmp(list, "s1") == 0) desc_mem = base; idx += addrc + sizec; @@ -567,6 +697,7 @@ static const struct eth_ops altera_tse_ops = { }; static const struct udevice_id altera_tse_ids[] = { + { .compatible = "altr,tse-msgdma-1.0", .data = ALT_MSGDMA }, { .compatible = "altr,tse-1.0", .data = ALT_SGDMA }, {} }; diff --git a/drivers/net/altera_tse.h b/drivers/net/altera_tse.h index fae2378..2b1af81 100644 --- a/drivers/net/altera_tse.h +++ b/drivers/net/altera_tse.h @@ -15,6 +15,7 @@ /* dma type */ #define ALT_SGDMA 0 +#define ALT_MSGDMA 1 /* SGDMA Stuff */ #define ALT_SGDMA_STATUS_BUSY_MSK BIT(4) @@ -87,6 +88,64 @@ struct alt_sgdma_registers { u32 descriptor_pad[3]; }; +/* mSGDMA Stuff */ + +/* mSGDMA extended descriptor format */ +struct msgdma_extended_desc { + u32 read_addr_lo; /* data buffer source address low bits */ + u32 write_addr_lo; /* data buffer destination address low bits */ + u32 len; + u32 burst_seq_num; + u32 stride; + u32 read_addr_hi; /* data buffer source address high bits */ + u32 write_addr_hi; /* data buffer destination address high bits */ + u32 control; /* characteristics of the transfer */ +}; + +/* mSGDMA descriptor control field bit definitions */ +#define MSGDMA_DESC_CTL_GEN_SOP BIT(8) +#define MSGDMA_DESC_CTL_GEN_EOP BIT(9) +#define MSGDMA_DESC_CTL_END_ON_EOP BIT(12) +#define MSGDMA_DESC_CTL_END_ON_LEN BIT(13) +#define MSGDMA_DESC_CTL_GO BIT(31) + +/* Tx buffer control flags */ +#define MSGDMA_DESC_CTL_TX_SINGLE (MSGDMA_DESC_CTL_GEN_SOP | \ + MSGDMA_DESC_CTL_GEN_EOP | \ + MSGDMA_DESC_CTL_GO) + +#define MSGDMA_DESC_CTL_RX_SINGLE (MSGDMA_DESC_CTL_END_ON_EOP | \ + MSGDMA_DESC_CTL_END_ON_LEN | \ + MSGDMA_DESC_CTL_GO) + +/* mSGDMA extended descriptor stride definitions */ +#define MSGDMA_DESC_TX_STRIDE 0x00010001 +#define MSGDMA_DESC_RX_STRIDE 0x00010001 + +/* mSGDMA dispatcher control and status register map */ +struct msgdma_csr { + u32 status; /* Read/Clear */ + u32 control; /* Read/Write */ + u32 rw_fill_level; + u32 resp_fill_level; /* bit 15:0 */ + u32 rw_seq_num; + u32 pad[3]; /* reserved */ +}; + +/* mSGDMA CSR status register bit definitions */ +#define MSGDMA_CSR_STAT_BUSY BIT(0) +#define MSGDMA_CSR_STAT_RESETTING BIT(6) +#define MSGDMA_CSR_STAT_MASK 0x3FF + +/* mSGDMA CSR control register bit definitions */ +#define MSGDMA_CSR_CTL_RESET BIT(1) + +/* mSGDMA response register map */ +struct msgdma_response { + u32 bytes_transferred; + u32 status; +}; + /* TSE Stuff */ #define ALTERA_TSE_CMD_TX_ENA_MSK BIT(0) #define ALTERA_TSE_CMD_RX_ENA_MSK BIT(1) @@ -159,6 +218,7 @@ struct altera_tse_priv { unsigned int tx_fifo_depth; void *rx_desc; void *tx_desc; + void *rx_resp; unsigned char *rx_buf; unsigned int phyaddr; unsigned int interface; -- cgit v1.1