summaryrefslogtreecommitdiff
path: root/drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c')
-rw-r--r--drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c2441
1 files changed, 0 insertions, 2441 deletions
diff --git a/drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c b/drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c
deleted file mode 100644
index dd4cd412aeb5..000000000000
--- a/drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c
+++ /dev/null
@@ -1,2441 +0,0 @@
-/* Cypress WestBridge OMAP3430 Kernel Hal source file (cyashalomap_kernel.c)
-## ===========================
-## Copyright (C) 2010 Cypress Semiconductor
-##
-## This program is free software; you can redistribute it and/or
-## modify it under the terms of the GNU General Public License
-## as published by the Free Software Foundation; either version 2
-## of the License, or (at your option) any later version.
-##
-## This program is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-## GNU General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with this program; if not, write to the Free Software
-## Foundation, Inc., 51 Franklin Street, Fifth Floor,
-## Boston, MA 02110-1301, USA.
-## ===========================
-*/
-
-#ifdef CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL
-
-#include <linux/fs.h>
-#include <linux/ioport.h>
-#include <linux/timer.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/scatterlist.h>
-#include <linux/mm.h>
-#include <linux/irq.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-/* include seems broken moving for patch submission
- * #include <mach/mux.h>
- * #include <mach/gpmc.h>
- * #include <mach/westbridge/westbridge-omap3-pnand-hal/cyashalomap_kernel.h>
- * #include <mach/westbridge/westbridge-omap3-pnand-hal/cyasomapdev_kernel.h>
- * #include <mach/westbridge/westbridge-omap3-pnand-hal/cyasmemmap.h>
- * #include <linux/westbridge/cyaserr.h>
- * #include <linux/westbridge/cyasregs.h>
- * #include <linux/westbridge/cyasdma.h>
- * #include <linux/westbridge/cyasintr.h>
- */
-#include <linux/../../arch/arm/plat-omap/include/plat/mux.h>
-#include <linux/../../arch/arm/plat-omap/include/plat/gpmc.h>
-#include "../plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyashalomap_kernel.h"
-#include "../plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasomapdev_kernel.h"
-#include "../plat-omap/include/mach/westbridge/westbridge-omap3-pnand-hal/cyasmemmap.h"
-#include "../../../include/linux/westbridge/cyaserr.h"
-#include "../../../include/linux/westbridge/cyasregs.h"
-#include "../../../include/linux/westbridge/cyasdma.h"
-#include "../../../include/linux/westbridge/cyasintr.h"
-
-#define HAL_REV "1.1.0"
-
-/*
- * uncomment to enable 16bit pnand interface
- */
-#define PNAND_16BIT_MODE
-
-/*
- * selects one of 3 versions of pnand_lbd_read()
- * PNAND_LBD_READ_NO_PFE - original 8/16 bit code
- * reads through the gpmc CONTROLLER REGISTERS
- * ENABLE_GPMC_PF_ENGINE - USES GPMC PFE FIFO reads, in 8 bit mode,
- * same speed as the above
- * PFE_LBD_READ_V2 - slightly diffrenet, performance same as above
- */
-#define PNAND_LBD_READ_NO_PFE
-/* #define ENABLE_GPMC_PF_ENGINE */
-/* #define PFE_LBD_READ_V2 */
-
-/*
- * westbrige astoria ISR options to limit number of
- * back to back DMA transfers per ISR interrupt
- */
-#define MAX_DRQ_LOOPS_IN_ISR 4
-
-/*
- * debug prints enabling
- *#define DBGPRN_ENABLED
- *#define DBGPRN_DMA_SETUP_RD
- *#define DBGPRN_DMA_SETUP_WR
- */
-
-
-/*
- * For performance reasons, we handle storage endpoint transfers up to 4 KB
- * within the HAL itself.
- */
- #define CYASSTORAGE_WRITE_EP_NUM (4)
- #define CYASSTORAGE_READ_EP_NUM (8)
-
-/*
- * size of DMA packet HAL can accept from Storage API
- * HAL will fragment it into smaller chunks that the P port can accept
- */
-#define CYASSTORAGE_MAX_XFER_SIZE (2*32768)
-
-/*
- * P port MAX DMA packet size according to interface/ep configurartion
- */
-#define HAL_DMA_PKT_SZ 512
-
-#define is_storage_e_p(ep) (((ep) == 2) || ((ep) == 4) || \
- ((ep) == 6) || ((ep) == 8))
-
-/*
- * persistent, stores current GPMC interface cfg mode
- */
-static uint8_t pnand_16bit;
-
-/*
- * keep processing new WB DRQ in ISR until all handled (performance feature)
- */
-#define PROCESS_MULTIPLE_DRQ_IN_ISR (1)
-
-
-/*
- * ASTORIA PNAND IF COMMANDS, CASDO - READ, CASDI - WRITE
- */
-#define CASDO 0x05
-#define CASDI 0x85
-#define RDPAGE_B1 0x00
-#define RDPAGE_B2 0x30
-#define PGMPAGE_B1 0x80
-#define PGMPAGE_B2 0x10
-
-/*
- * The type of DMA operation, per endpoint
- */
-typedef enum cy_as_hal_dma_type {
- cy_as_hal_read,
- cy_as_hal_write,
- cy_as_hal_none
-} cy_as_hal_dma_type;
-
-
-/*
- * SG list halpers defined in scaterlist.h
-#define sg_is_chain(sg) ((sg)->page_link & 0x01)
-#define sg_is_last(sg) ((sg)->page_link & 0x02)
-#define sg_chain_ptr(sg) \
- ((struct scatterlist *) ((sg)->page_link & ~0x03))
-*/
-typedef struct cy_as_hal_endpoint_dma {
- cy_bool buffer_valid;
- uint8_t *data_p;
- uint32_t size;
- /*
- * sg_list_enabled - if true use, r/w DMA transfers use sg list,
- * FALSE use pointer to a buffer
- * sg_p - pointer to the owner's sg list, of there is such
- * (like blockdriver)
- * dma_xfer_sz - size of the next dma xfer on P port
- * seg_xfer_cnt - counts xfered bytes for in current sg_list
- * memory segment
- * req_xfer_cnt - total number of bytes transferred so far in
- * current request
- * req_length - total request length
- */
- bool sg_list_enabled;
- struct scatterlist *sg_p;
- uint16_t dma_xfer_sz;
- uint32_t seg_xfer_cnt;
- uint16_t req_xfer_cnt;
- uint16_t req_length;
- cy_as_hal_dma_type type;
- cy_bool pending;
-} cy_as_hal_endpoint_dma;
-
-/*
- * The list of OMAP devices (should be one)
- */
-static cy_as_omap_dev_kernel *m_omap_list_p;
-
-/*
- * The callback to call after DMA operations are complete
- */
-static cy_as_hal_dma_complete_callback callback;
-
-/*
- * Pending data size for the endpoints
- */
-static cy_as_hal_endpoint_dma end_points[16];
-
-/*
- * Forward declaration
- */
-static void cy_handle_d_r_q_interrupt(cy_as_omap_dev_kernel *dev_p);
-
-static uint16_t intr_sequence_num;
-static uint8_t intr__enable;
-spinlock_t int_lock;
-
-static u32 iomux_vma;
-static u32 csa_phy;
-
-/*
- * gpmc I/O registers VMA
- */
-static u32 gpmc_base;
-
-/*
- * gpmc data VMA associated with CS4 (ASTORIA CS on GPMC)
- */
-static u32 gpmc_data_vma;
-static u32 ndata_reg_vma;
-static u32 ncmd_reg_vma;
-static u32 naddr_reg_vma;
-
-/*
- * fwd declarations
- */
-static void p_nand_lbd_read(u16 col_addr, u32 row_addr, u16 count, void *buff);
-static void p_nand_lbd_write(u16 col_addr, u32 row_addr, u16 count, void *buff);
-static inline u16 __attribute__((always_inline))
- ast_p_nand_casdo_read(u8 reg_addr8);
-static inline void __attribute__((always_inline))
- ast_p_nand_casdi_write(u8 reg_addr8, u16 data);
-
-/*
- * prints given number of omap registers
- */
-static void cy_as_hal_print_omap_regs(char *name_prefix,
- u8 name_base, u32 virt_base, u16 count)
-{
- u32 reg_val, reg_addr;
- u16 i;
- cy_as_hal_print_message(KERN_INFO "\n");
- for (i = 0; i < count; i++) {
-
- reg_addr = virt_base + (i*4);
- /* use virtual addresses here*/
- reg_val = __raw_readl(reg_addr);
- cy_as_hal_print_message(KERN_INFO "%s_%d[%8.8x]=%8.8x\n",
- name_prefix, name_base+i,
- reg_addr, reg_val);
- }
-}
-
-/*
- * setMUX function for a pad + additional pad flags
- */
-static u16 omap_cfg_reg_L(u32 pad_func_index)
-{
- static u8 sanity_check = 1;
-
- u32 reg_vma;
- u16 cur_val, wr_val, rdback_val;
-
- /*
- * do sanity check on the omap_mux_pin_cfg[] table
- */
- cy_as_hal_print_message(KERN_INFO" OMAP pins user_pad cfg ");
- if (sanity_check) {
- if ((omap_mux_pin_cfg[END_OF_TABLE].name[0] == 'E') &&
- (omap_mux_pin_cfg[END_OF_TABLE].name[1] == 'N') &&
- (omap_mux_pin_cfg[END_OF_TABLE].name[2] == 'D')) {
-
- cy_as_hal_print_message(KERN_INFO
- "table is good.\n");
- } else {
- cy_as_hal_print_message(KERN_WARNING
- "table is bad, fix it");
- }
- /*
- * do it only once
- */
- sanity_check = 0;
- }
-
- /*
- * get virtual address to the PADCNF_REG
- */
- reg_vma = (u32)iomux_vma + omap_mux_pin_cfg[pad_func_index].offset;
-
- /*
- * add additional USER PU/PD/EN flags
- */
- wr_val = omap_mux_pin_cfg[pad_func_index].mux_val;
- cur_val = IORD16(reg_vma);
-
- /*
- * PADCFG regs 16 bit long, packed into 32 bit regs,
- * can also be accessed as u16
- */
- IOWR16(reg_vma, wr_val);
- rdback_val = IORD16(reg_vma);
-
- /*
- * in case if the caller wants to save the old value
- */
- return wr_val;
-}
-
-#define BLKSZ_4K 0x1000
-
-/*
- * switch GPMC DATA bus mode
- */
-void cy_as_hal_gpmc_enable_16bit_bus(bool dbus16_enabled)
-{
- uint32_t tmp32;
-
- /*
- * disable gpmc CS4 operation 1st
- */
- tmp32 = gpmc_cs_read_reg(AST_GPMC_CS,
- GPMC_CS_CONFIG7) & ~GPMC_CONFIG7_CSVALID;
- gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG7, tmp32);
-
- /*
- * GPMC NAND data bus can be 8 or 16 bit wide
- */
- if (dbus16_enabled) {
- DBGPRN("enabling 16 bit bus\n");
- gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG1,
- (GPMC_CONFIG1_DEVICETYPE(2) |
- GPMC_CONFIG1_WAIT_PIN_SEL(2) |
- GPMC_CONFIG1_DEVICESIZE_16)
- );
- } else {
- DBGPRN(KERN_INFO "enabling 8 bit bus\n");
- gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG1,
- (GPMC_CONFIG1_DEVICETYPE(2) |
- GPMC_CONFIG1_WAIT_PIN_SEL(2))
- );
- }
-
- /*
- * re-enable astoria CS operation on GPMC
- */
- gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG7,
- (tmp32 | GPMC_CONFIG7_CSVALID));
-
- /*
- *remember the state
- */
- pnand_16bit = dbus16_enabled;
-}
-
-static int cy_as_hal_gpmc_init(void)
-{
- u32 tmp32;
- int err;
- struct gpmc_timings timings;
-
- gpmc_base = (u32)ioremap_nocache(OMAP34XX_GPMC_BASE, BLKSZ_4K);
- DBGPRN(KERN_INFO "kernel has gpmc_base=%x , val@ the base=%x",
- gpmc_base, __raw_readl(gpmc_base)
- );
-
- /*
- * these are globals are full VMAs of the gpmc_base above
- */
- ncmd_reg_vma = GPMC_VMA(AST_GPMC_NAND_CMD);
- naddr_reg_vma = GPMC_VMA(AST_GPMC_NAND_ADDR);
- ndata_reg_vma = GPMC_VMA(AST_GPMC_NAND_DATA);
-
- /*
- * request GPMC CS for ASTORIA request
- */
- if (gpmc_cs_request(AST_GPMC_CS, SZ_16M, (void *)&csa_phy) < 0) {
- cy_as_hal_print_message(KERN_ERR "error failed to request"
- "ncs4 for ASTORIA\n");
- return -1;
- } else {
- DBGPRN(KERN_INFO "got phy_addr:%x for "
- "GPMC CS%d GPMC_CFGREG7[CS4]\n",
- csa_phy, AST_GPMC_CS);
- }
-
- /*
- * request VM region for 4K addr space for chip select 4 phy address
- * technically we don't need it for NAND devices, but do it anyway
- * so that data read/write bus cycle can be triggered by reading
- * or writing this mem region
- */
- if (!request_mem_region(csa_phy, BLKSZ_4K, "AST_OMAP_HAL")) {
- err = -EBUSY;
- cy_as_hal_print_message(KERN_ERR "error MEM region "
- "request for phy_addr:%x failed\n",
- csa_phy);
- goto out_free_cs;
- }
-
- /*
- * REMAP mem region associated with our CS
- */
- gpmc_data_vma = (u32)ioremap_nocache(csa_phy, BLKSZ_4K);
- if (!gpmc_data_vma) {
- err = -ENOMEM;
- cy_as_hal_print_message(KERN_ERR "error- ioremap()"
- "for phy_addr:%x failed", csa_phy);
-
- goto out_release_mem_region;
- }
- cy_as_hal_print_message(KERN_INFO "ioremap(%x) returned vma=%x\n",
- csa_phy, gpmc_data_vma);
-
- gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG1,
- (GPMC_CONFIG1_DEVICETYPE(2) |
- GPMC_CONFIG1_WAIT_PIN_SEL(2)));
-
- memset(&timings, 0, sizeof(timings));
-
- /* cs timing */
- timings.cs_on = WB_GPMC_CS_t_o_n;
- timings.cs_wr_off = WB_GPMC_BUSCYC_t;
- timings.cs_rd_off = WB_GPMC_BUSCYC_t;
-
- /* adv timing */
- timings.adv_on = WB_GPMC_ADV_t_o_n;
- timings.adv_rd_off = WB_GPMC_BUSCYC_t;
- timings.adv_wr_off = WB_GPMC_BUSCYC_t;
-
- /* oe timing */
- timings.oe_on = WB_GPMC_OE_t_o_n;
- timings.oe_off = WB_GPMC_OE_t_o_f_f;
- timings.access = WB_GPMC_RD_t_a_c_c;
- timings.rd_cycle = WB_GPMC_BUSCYC_t;
-
- /* we timing */
- timings.we_on = WB_GPMC_WE_t_o_n;
- timings.we_off = WB_GPMC_WE_t_o_f_f;
- timings.wr_access = WB_GPMC_WR_t_a_c_c;
- timings.wr_cycle = WB_GPMC_BUSCYC_t;
-
- timings.page_burst_access = WB_GPMC_BUSCYC_t;
- timings.wr_data_mux_bus = WB_GPMC_BUSCYC_t;
- gpmc_cs_set_timings(AST_GPMC_CS, &timings);
-
- cy_as_hal_print_omap_regs("GPMC_CONFIG", 1,
- GPMC_VMA(GPMC_CFG_REG(1, AST_GPMC_CS)), 7);
-
- /*
- * DISABLE cs4, NOTE GPMC REG7 is already configured
- * at this point by gpmc_cs_request
- */
- tmp32 = gpmc_cs_read_reg(AST_GPMC_CS, GPMC_CS_CONFIG7) &
- ~GPMC_CONFIG7_CSVALID;
- gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG7, tmp32);
-
- /*
- * PROGRAM chip select Region, (see OMAP3430 TRM PAGE 1088)
- */
- gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG7,
- (AS_CS_MASK | AS_CS_BADDR));
-
- /*
- * by default configure GPMC into 8 bit mode
- * (to match astoria default mode)
- */
- gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG1,
- (GPMC_CONFIG1_DEVICETYPE(2) |
- GPMC_CONFIG1_WAIT_PIN_SEL(2)));
-
- /*
- * ENABLE astoria cs operation on GPMC
- */
- gpmc_cs_write_reg(AST_GPMC_CS, GPMC_CS_CONFIG7,
- (tmp32 | GPMC_CONFIG7_CSVALID));
-
- /*
- * No method currently exists to write this register through GPMC APIs
- * need to change WAIT2 polarity
- */
- tmp32 = IORD32(GPMC_VMA(GPMC_CONFIG_REG));
- tmp32 = tmp32 | NAND_FORCE_POSTED_WRITE_B | 0x40;
- IOWR32(GPMC_VMA(GPMC_CONFIG_REG), tmp32);
-
- tmp32 = IORD32(GPMC_VMA(GPMC_CONFIG_REG));
- cy_as_hal_print_message("GPMC_CONFIG_REG=0x%x\n", tmp32);
-
- return 0;
-
-out_release_mem_region:
- release_mem_region(csa_phy, BLKSZ_4K);
-
-out_free_cs:
- gpmc_cs_free(AST_GPMC_CS);
-
- return err;
-}
-
-/*
- * west bridge astoria ISR (Interrupt handler)
- */
-static irqreturn_t cy_astoria_int_handler(int irq,
- void *dev_id, struct pt_regs *regs)
-{
- cy_as_omap_dev_kernel *dev_p;
- uint16_t read_val = 0;
- uint16_t mask_val = 0;
-
- /*
- * debug stuff, counts number of loops per one intr trigger
- */
- uint16_t drq_loop_cnt = 0;
- uint8_t irq_pin;
- /*
- * flags to watch
- */
- const uint16_t sentinel = (CY_AS_MEM_P0_INTR_REG_MCUINT |
- CY_AS_MEM_P0_INTR_REG_MBINT |
- CY_AS_MEM_P0_INTR_REG_PMINT |
- CY_AS_MEM_P0_INTR_REG_PLLLOCKINT);
-
- /*
- * sample IRQ pin level (just for statistics)
- */
- irq_pin = __gpio_get_value(AST_INT);
-
- /*
- * this one just for debugging
- */
- intr_sequence_num++;
-
- /*
- * astoria device handle
- */
- dev_p = dev_id;
-
- /*
- * read Astoria intr register
- */
- read_val = cy_as_hal_read_register((cy_as_hal_device_tag)dev_p,
- CY_AS_MEM_P0_INTR_REG);
-
- /*
- * save current mask value
- */
- mask_val = cy_as_hal_read_register((cy_as_hal_device_tag)dev_p,
- CY_AS_MEM_P0_INT_MASK_REG);
-
- DBGPRN("<1>HAL__intr__enter:_seq:%d, P0_INTR_REG:%x\n",
- intr_sequence_num, read_val);
-
- /*
- * Disable WB interrupt signal generation while we are in ISR
- */
- cy_as_hal_write_register((cy_as_hal_device_tag)dev_p,
- CY_AS_MEM_P0_INT_MASK_REG, 0x0000);
-
- /*
- * this is a DRQ Interrupt
- */
- if (read_val & CY_AS_MEM_P0_INTR_REG_DRQINT) {
-
- do {
- /*
- * handle DRQ interrupt
- */
- drq_loop_cnt++;
-
- cy_handle_d_r_q_interrupt(dev_p);
-
- /*
- * spending to much time in ISR may impact
- * average system performance
- */
- if (drq_loop_cnt >= MAX_DRQ_LOOPS_IN_ISR)
- break;
-
- /*
- * Keep processing if there is another DRQ int flag
- */
- } while (cy_as_hal_read_register((cy_as_hal_device_tag)dev_p,
- CY_AS_MEM_P0_INTR_REG) &
- CY_AS_MEM_P0_INTR_REG_DRQINT);
- }
-
- if (read_val & sentinel)
- cy_as_intr_service_interrupt((cy_as_hal_device_tag)dev_p);
-
- DBGPRN("<1>_hal:_intr__exit seq:%d, mask=%4.4x,"
- "int_pin:%d DRQ_jobs:%d\n",
- intr_sequence_num,
- mask_val,
- irq_pin,
- drq_loop_cnt);
-
- /*
- * re-enable WB hw interrupts
- */
- cy_as_hal_write_register((cy_as_hal_device_tag)dev_p,
- CY_AS_MEM_P0_INT_MASK_REG, mask_val);
-
- return IRQ_HANDLED;
-}
-
-static int cy_as_hal_configure_interrupts(void *dev_p)
-{
- int result;
- int irq_pin = AST_INT;
-
- irq_set_irq_type(OMAP_GPIO_IRQ(irq_pin), IRQ_TYPE_LEVEL_LOW);
-
- /*
- * for shared IRQS must provide non NULL device ptr
- * othervise the int won't register
- * */
- result = request_irq(OMAP_GPIO_IRQ(irq_pin),
- (irq_handler_t)cy_astoria_int_handler,
- IRQF_SHARED, "AST_INT#", dev_p);
-
- if (result == 0) {
- /*
- * OMAP_GPIO_IRQ(irq_pin) - omap logical IRQ number
- * assigned to this interrupt
- * OMAP_GPIO_BIT(AST_INT, GPIO_IRQENABLE1) - print status
- * of AST_INT GPIO IRQ_ENABLE FLAG
- */
- cy_as_hal_print_message(KERN_INFO"AST_INT omap_pin:"
- "%d assigned IRQ #%d IRQEN1=%d\n",
- irq_pin,
- OMAP_GPIO_IRQ(irq_pin),
- OMAP_GPIO_BIT(AST_INT, GPIO_IRQENABLE1)
- );
- } else {
- cy_as_hal_print_message("cyasomaphal: interrupt "
- "failed to register\n");
- gpio_free(irq_pin);
- cy_as_hal_print_message(KERN_WARNING
- "ASTORIA: can't get assigned IRQ"
- "%i for INT#\n", OMAP_GPIO_IRQ(irq_pin));
- }
-
- return result;
-}
-
-/*
- * initialize OMAP pads/pins to user defined functions
- */
-static void cy_as_hal_init_user_pads(user_pad_cfg_t *pad_cfg_tab)
-{
- /*
- * browse through the table an dinitiaze the pins
- */
- u32 in_level = 0;
- u16 tmp16, mux_val;
-
- while (pad_cfg_tab->name != NULL) {
-
- if (gpio_request(pad_cfg_tab->pin_num, NULL) == 0) {
-
- pad_cfg_tab->valid = 1;
- mux_val = omap_cfg_reg_L(pad_cfg_tab->mux_func);
-
- /*
- * always set drv level before changing out direction
- */
- __gpio_set_value(pad_cfg_tab->pin_num,
- pad_cfg_tab->drv);
-
- /*
- * "0" - OUT, "1", input omap_set_gpio_direction
- * (pad_cfg_tab->pin_num, pad_cfg_tab->dir);
- */
- if (pad_cfg_tab->dir)
- gpio_direction_input(pad_cfg_tab->pin_num);
- else
- gpio_direction_output(pad_cfg_tab->pin_num,
- pad_cfg_tab->drv);
-
- /* sample the pin */
- in_level = __gpio_get_value(pad_cfg_tab->pin_num);
-
- cy_as_hal_print_message(KERN_INFO "configured %s to "
- "OMAP pad_%d, DIR=%d "
- "DOUT=%d, DIN=%d\n",
- pad_cfg_tab->name,
- pad_cfg_tab->pin_num,
- pad_cfg_tab->dir,
- pad_cfg_tab->drv,
- in_level
- );
- } else {
- /*
- * get the pad_mux value to check on the pin_function
- */
- cy_as_hal_print_message(KERN_INFO "couldn't cfg pin %d"
- "for signal %s, its already taken\n",
- pad_cfg_tab->pin_num,
- pad_cfg_tab->name);
- }
-
- tmp16 = *(u16 *)PADCFG_VMA
- (omap_mux_pin_cfg[pad_cfg_tab->mux_func].offset);
-
- cy_as_hal_print_message(KERN_INFO "GPIO_%d(PAD_CFG=%x,OE=%d"
- "DOUT=%d, DIN=%d IRQEN=%d)\n\n",
- pad_cfg_tab->pin_num, tmp16,
- OMAP_GPIO_BIT(pad_cfg_tab->pin_num, GPIO_OE),
- OMAP_GPIO_BIT(pad_cfg_tab->pin_num, GPIO_DATA_OUT),
- OMAP_GPIO_BIT(pad_cfg_tab->pin_num, GPIO_DATA_IN),
- OMAP_GPIO_BIT(pad_cfg_tab->pin_num, GPIO_IRQENABLE1)
- );
-
- /*
- * next pad_cfg deriptor
- */
- pad_cfg_tab++;
- }
-
- cy_as_hal_print_message(KERN_INFO"pads configured\n");
-}
-
-
-/*
- * release gpios taken by the module
- */
-static void cy_as_hal_release_user_pads(user_pad_cfg_t *pad_cfg_tab)
-{
- while (pad_cfg_tab->name != NULL) {
-
- if (pad_cfg_tab->valid) {
- gpio_free(pad_cfg_tab->pin_num);
- pad_cfg_tab->valid = 0;
- cy_as_hal_print_message(KERN_INFO "GPIO_%d "
- "released from %s\n",
- pad_cfg_tab->pin_num,
- pad_cfg_tab->name);
- } else {
- cy_as_hal_print_message(KERN_INFO "no release "
- "for %s, GPIO_%d, wasn't acquired\n",
- pad_cfg_tab->name,
- pad_cfg_tab->pin_num);
- }
- pad_cfg_tab++;
- }
-}
-
-void cy_as_hal_config_c_s_mux(void)
-{
- /*
- * FORCE the GPMC CS4 pin (it is in use by the zoom system)
- */
- omap_cfg_reg_L(T8_OMAP3430_GPMC_n_c_s4);
-}
-EXPORT_SYMBOL(cy_as_hal_config_c_s_mux);
-
-/*
- * inits all omap h/w
- */
-uint32_t cy_as_hal_processor_hw_init(void)
-{
- int i, err;
-
- cy_as_hal_print_message(KERN_INFO "init OMAP3430 hw...\n");
-
- iomux_vma = (u32)ioremap_nocache(
- (u32)CTLPADCONF_BASE_ADDR, CTLPADCONF_SIZE);
- cy_as_hal_print_message(KERN_INFO "PADCONF_VMA=%x val=%x\n",
- iomux_vma, IORD32(iomux_vma));
-
- /*
- * remap gpio banks
- */
- for (i = 0; i < 6; i++) {
- gpio_vma_tab[i].virt_addr = (u32)ioremap_nocache(
- gpio_vma_tab[i].phy_addr,
- gpio_vma_tab[i].size);
-
- cy_as_hal_print_message(KERN_INFO "%s virt_addr=%x\n",
- gpio_vma_tab[i].name,
- (u32)gpio_vma_tab[i].virt_addr);
- }
-
- /*
- * force OMAP_GPIO_126 to rleased state,
- * will be configured to drive reset
- */
- gpio_free(AST_RESET);
-
- /*
- *same thing with AStoria CS pin
- */
- gpio_free(AST_CS);
-
- /*
- * initialize all the OMAP pads connected to astoria
- */
- cy_as_hal_init_user_pads(user_pad_cfg);
-
- err = cy_as_hal_gpmc_init();
- if (err < 0)
- cy_as_hal_print_message(KERN_INFO"gpmc init failed:%d", err);
-
- cy_as_hal_config_c_s_mux();
-
- return gpmc_data_vma;
-}
-EXPORT_SYMBOL(cy_as_hal_processor_hw_init);
-
-void cy_as_hal_omap_hardware_deinit(cy_as_omap_dev_kernel *dev_p)
-{
- /*
- * free omap hw resources
- */
- if (gpmc_data_vma != 0)
- iounmap((void *)gpmc_data_vma);
-
- if (csa_phy != 0)
- release_mem_region(csa_phy, BLKSZ_4K);
-
- gpmc_cs_free(AST_GPMC_CS);
-
- free_irq(OMAP_GPIO_IRQ(AST_INT), dev_p);
-
- cy_as_hal_release_user_pads(user_pad_cfg);
-}
-
-/*
- * These are the functions that are not part of the
- * HAL layer, but are required to be called for this HAL
- */
-
-/*
- * Called On AstDevice LKM exit
- */
-int stop_o_m_a_p_kernel(const char *pgm, cy_as_hal_device_tag tag)
-{
- cy_as_omap_dev_kernel *dev_p = (cy_as_omap_dev_kernel *)tag;
-
- /*
- * TODO: Need to disable WB interrupt handlere 1st
- */
- if (0 == dev_p)
- return 1;
-
- cy_as_hal_print_message("<1>_stopping OMAP34xx HAL layer object\n");
- if (dev_p->m_sig != CY_AS_OMAP_KERNEL_HAL_SIG) {
- cy_as_hal_print_message("<1>%s: %s: bad HAL tag\n",
- pgm, __func__);
- return 1;
- }
-
- /*
- * disable interrupt
- */
- cy_as_hal_write_register((cy_as_hal_device_tag)dev_p,
- CY_AS_MEM_P0_INT_MASK_REG, 0x0000);
-
-#if 0
- if (dev_p->thread_flag == 0) {
- dev_p->thread_flag = 1;
- wait_for_completion(&dev_p->thread_complete);
- cy_as_hal_print_message("cyasomaphal:"
- "done cleaning thread\n");
- cy_as_hal_destroy_sleep_channel(&dev_p->thread_sc);
- }
-#endif
-
- cy_as_hal_omap_hardware_deinit(dev_p);
-
- /*
- * Rearrange the list
- */
- if (m_omap_list_p == dev_p)
- m_omap_list_p = dev_p->m_next_p;
-
- cy_as_hal_free(dev_p);
-
- cy_as_hal_print_message(KERN_INFO"OMAP_kernel_hal stopped\n");
- return 0;
-}
-
-int omap_start_intr(cy_as_hal_device_tag tag)
-{
- cy_as_omap_dev_kernel *dev_p = (cy_as_omap_dev_kernel *)tag;
- int ret = 0;
- const uint16_t mask = CY_AS_MEM_P0_INTR_REG_DRQINT |
- CY_AS_MEM_P0_INTR_REG_MBINT;
-
- /*
- * register for interrupts
- */
- ret = cy_as_hal_configure_interrupts(dev_p);
-
- /*
- * enable only MBox & DRQ interrupts for now
- */
- cy_as_hal_write_register((cy_as_hal_device_tag)dev_p,
- CY_AS_MEM_P0_INT_MASK_REG, mask);
-
- return 1;
-}
-
-/*
- * Below are the functions that communicate with the WestBridge device.
- * These are system dependent and must be defined by the HAL layer
- * for a given system.
- */
-
-/*
- * GPMC NAND command+addr write phase
- */
-static inline void nand_cmd_n_addr(u8 cmdb1, u16 col_addr, u32 row_addr)
-{
- /*
- * byte order on the bus <cmd> <CA0,CA1,RA0,RA1, RA2>
- */
- u32 tmpa32 = ((row_addr << 16) | col_addr);
- u8 RA2 = (u8)(row_addr >> 16);
-
- if (!pnand_16bit) {
- /*
- * GPMC PNAND 8bit BUS
- */
- /*
- * CMD1
- */
- IOWR8(ncmd_reg_vma, cmdb1);
-
- /*
- *pnand bus: <CA0,CA1,RA0,RA1>
- */
- IOWR32(naddr_reg_vma, tmpa32);
-
- /*
- * <RA2> , always zero
- */
- IOWR8(naddr_reg_vma, RA2);
-
- } else {
- /*
- * GPMC PNAND 16bit BUS , in 16 bit mode CMD
- * and ADDR sent on [d7..d0]
- */
- uint8_t CA0, CA1, RA0, RA1;
- CA0 = tmpa32 & 0x000000ff;
- CA1 = (tmpa32 >> 8) & 0x000000ff;
- RA0 = (tmpa32 >> 16) & 0x000000ff;
- RA1 = (tmpa32 >> 24) & 0x000000ff;
-
- /*
- * can't use 32 bit writes here omap will not serialize
- * them to lower half in16 bit mode
- */
-
- /*
- *pnand bus: <CMD1, CA0,CA1,RA0,RA1, RA2 (always zero)>
- */
- IOWR8(ncmd_reg_vma, cmdb1);
- IOWR8(naddr_reg_vma, CA0);
- IOWR8(naddr_reg_vma, CA1);
- IOWR8(naddr_reg_vma, RA0);
- IOWR8(naddr_reg_vma, RA1);
- IOWR8(naddr_reg_vma, RA2);
- }
-}
-
-/*
- * spin until r/b goes high
- */
-inline int wait_rn_b_high(void)
-{
- u32 w_spins = 0;
-
- /*
- * TODO: note R/b may go low here, need to spin until high
- * while (omap_get_gpio_datain(AST_RnB) == 0) {
- * w_spins++;
- * }
- * if (OMAP_GPIO_BIT(AST_RnB, GPIO_DATA_IN) == 0) {
- *
- * while (OMAP_GPIO_BIT(AST_RnB, GPIO_DATA_IN) == 0) {
- * w_spins++;
- * }
- * printk("<1>RnB=0!:%d\n",w_spins);
- * }
- */
- return w_spins;
-}
-
-#ifdef ENABLE_GPMC_PF_ENGINE
-/* #define PFE_READ_DEBUG
- * PNAND block read with OMAP PFE enabled
- * status: Not tested, NW, broken , etc
- */
-static void p_nand_lbd_read(u16 col_addr, u32 row_addr, u16 count, void *buff)
-{
- uint16_t w32cnt;
- uint32_t *ptr32;
- uint8_t *ptr8;
- uint8_t bytes_in_fifo;
-
- /* debug vars*/
-#ifdef PFE_READ_DEBUG
- uint32_t loop_limit;
- uint16_t bytes_read = 0;
-#endif
-
- /*
- * configure the prefetch engine
- */
- uint32_t tmp32;
- uint32_t pfe_status;
-
- /*
- * DISABLE GPMC CS4 operation 1st, this is
- * in case engine is be already disabled
- */
- IOWR32(GPMC_VMA(GPMC_PREFETCH_CONTROL), 0x0);
- IOWR32(GPMC_VMA(GPMC_PREFETCH_CONFIG1), GPMC_PREFETCH_CONFIG1_VAL);
- IOWR32(GPMC_VMA(GPMC_PREFETCH_CONFIG2), count);
-
-#ifdef PFE_READ_DEBUG
- tmp32 = IORD32(GPMC_VMA(GPMC_PREFETCH_CONFIG1));
- if (tmp32 != GPMC_PREFETCH_CONFIG1_VAL) {
- printk(KERN_INFO "<1> prefetch is CONFIG1 read val:%8.8x, != VAL written:%8.8x\n",
- tmp32, GPMC_PREFETCH_CONFIG1_VAL);
- tmp32 = IORD32(GPMC_VMA(GPMC_PREFETCH_STATUS));
- printk(KERN_INFO "<1> GPMC_PREFETCH_STATUS : %8.8x\n", tmp32);
- }
-
- /*
- *sanity check 2
- */
- tmp32 = IORD32(GPMC_VMA(GPMC_PREFETCH_CONFIG2));
- if (tmp32 != (count))
- printk(KERN_INFO "<1> GPMC_PREFETCH_CONFIG2 read val:%d, "
- "!= VAL written:%d\n", tmp32, count);
-#endif
-
- /*
- * ISSUE PNAND CMD+ADDR, note gpmc puts 32b words
- * on the bus least sig. byte 1st
- */
- nand_cmd_n_addr(RDPAGE_B1, col_addr, row_addr);
-
- IOWR8(ncmd_reg_vma, RDPAGE_B2);
-
- /*
- * start the prefetch engine
- */
- IOWR32(GPMC_VMA(GPMC_PREFETCH_CONTROL), 0x1);
-
- ptr32 = buff;
-
- while (1) {
- /*
- * GPMC PFE service loop
- */
- do {
- /*
- * spin until PFE fetched some
- * PNAND bus words in the FIFO
- */
- pfe_status = IORD32(GPMC_VMA(GPMC_PREFETCH_STATUS));
- bytes_in_fifo = (pfe_status >> 24) & 0x7f;
- } while (bytes_in_fifo == 0);
-
- /* whole 32 bit words in fifo */
- w32cnt = bytes_in_fifo >> 2;
-
-#if 0
- /*
- *NOTE: FIFO_PTR indicates number of NAND bus words bytes
- * already received in the FIFO and available to be read
- * by DMA or MPU whether COUNTVAL indicates number of BUS
- * words yet to be read from PNAND bus words
- */
- printk(KERN_ERR "<1> got PF_STATUS:%8.8x FIFO_PTR:%d, COUNTVAL:%d, w32cnt:%d\n",
- pfe_status, bytes_in_fifo,
- (pfe_status & 0x3fff), w32cnt);
-#endif
-
- while (w32cnt--)
- *ptr32++ = IORD32(gpmc_data_vma);
-
- if ((pfe_status & 0x3fff) == 0) {
- /*
- * PFE acc angine done, there still may be data leftover
- * in the FIFO re-read FIFO BYTE counter (check for
- * leftovers from 32 bit read accesses above)
- */
- bytes_in_fifo = (IORD32(
- GPMC_VMA(GPMC_PREFETCH_STATUS)) >> 24) & 0x7f;
-
- /*
- * NOTE we may still have one word left in the fifo
- * read it out
- */
- ptr8 = ptr32;
- switch (bytes_in_fifo) {
-
- case 0:
- /*
- * nothing to do we already read the
- * FIFO out with 32 bit accesses
- */
- break;
- case 1:
- /*
- * this only possible
- * for 8 bit pNAND only
- */
- *ptr8 = IORD8(gpmc_data_vma);
- break;
-
- case 2:
- /*
- * this one can occur in either modes
- */
- *(uint16_t *)ptr8 = IORD16(gpmc_data_vma);
- break;
-
- case 3:
- /*
- * this only possible for 8 bit pNAND only
- */
- *(uint16_t *)ptr8 = IORD16(gpmc_data_vma);
- ptr8 += 2;
- *ptr8 = IORD8(gpmc_data_vma);
- break;
-
- case 4:
- /*
- * shouldn't happen, but has been seen
- * in 8 bit mode
- */
- *ptr32 = IORD32(gpmc_data_vma);
- break;
-
- default:
- printk(KERN_ERR"<1>_error: PFE FIFO bytes leftover is not read:%d\n",
- bytes_in_fifo);
- break;
- }
- /*
- * read is completed, get out of the while(1) loop
- */
- break;
- }
- }
-}
-#endif
-
-#ifdef PFE_LBD_READ_V2
-/*
- * PFE engine assisted reads with the 64 byte blocks
- */
-static void p_nand_lbd_read(u16 col_addr, u32 row_addr, u16 count, void *buff)
-{
- uint8_t rd_cnt;
- uint32_t *ptr32;
- uint8_t *ptr8;
- uint16_t reminder;
- uint32_t pfe_status;
-
- /*
- * ISSUE PNAND CMD+ADDR
- * note gpmc puts 32b words on the bus least sig. byte 1st
- */
- nand_cmd_n_addr(RDPAGE_B1, col_addr, row_addr);
- IOWR8(ncmd_reg_vma, RDPAGE_B2);
-
- /*
- * setup PFE block
- * count - OMAP number of bytes to access on pnand bus
- */
-
- IOWR32(GPMC_VMA(GPMC_PREFETCH_CONFIG1), GPMC_PREFETCH_CONFIG1_VAL);
- IOWR32(GPMC_VMA(GPMC_PREFETCH_CONFIG2), count);
- IOWR32(GPMC_VMA(GPMC_PREFETCH_CONTROL), 0x1);
-
- ptr32 = buff;
-
- do {
- pfe_status = IORD32(GPMC_VMA(GPMC_PREFETCH_STATUS));
- rd_cnt = pfe_status >> (24+2);
-
- while (rd_cnt--)
- *ptr32++ = IORD32(gpmc_data_vma);
-
- } while (pfe_status & 0x3fff);
-
- /*
- * read out the leftover
- */
- ptr8 = ptr32;
- rd_cnt = (IORD32(GPMC_VMA(GPMC_PREFETCH_STATUS)) >> 24) & 0x7f;
-
- while (rd_cnt--)
- *ptr8++ = IORD8(gpmc_data_vma);
-}
-#endif
-
-#ifdef PNAND_LBD_READ_NO_PFE
-/*
- * Endpoint buffer read w/o OMAP GPMC Prefetch Engine
- * the original working code, works at max speed for 8 bit xfers
- * for 16 bit the bus diagram has gaps
- */
-static void p_nand_lbd_read(u16 col_addr, u32 row_addr, u16 count, void *buff)
-{
- uint16_t w32cnt;
- uint32_t *ptr32;
- uint16_t *ptr16;
- uint16_t remainder;
-
- DBGPRN("<1> %s(): NO_PFE\n", __func__);
-
- ptr32 = buff;
- /* number of whole 32 bit words in the transfer */
- w32cnt = count >> 2;
-
- /* remainder, in bytes(0..3) */
- remainder = count & 03;
-
- /*
- * note gpmc puts 32b words on the bus least sig. byte 1st
- */
- nand_cmd_n_addr(RDPAGE_B1, col_addr, row_addr);
- IOWR8(ncmd_reg_vma, RDPAGE_B2);
-
- /*
- * read data by 32 bit chunks
- */
- while (w32cnt--)
- *ptr32++ = IORD32(ndata_reg_vma);
-
- /*
- * now do the remainder(it can be 0, 1, 2 or 3)
- * same code for both 8 & 16 bit bus
- * do 1 or 2 MORE words
- */
- ptr16 = (uint16_t *)ptr32;
-
- switch (remainder) {
- case 1:
- /* read one 16 bit word
- * IN 8 BIT WE NEED TO READ even number of bytes
- */
- case 2:
- *ptr16 = IORD16(ndata_reg_vma);
- break;
- case 3:
- /*
- * for 3 bytes read 2 16 bit words
- */
- *ptr16++ = IORD16(ndata_reg_vma);
- *ptr16 = IORD16(ndata_reg_vma);
- break;
- default:
- /*
- * remainder is 0
- */
- break;
- }
-}
-#endif
-
-/*
- * uses LBD mode to write N bytes into astoria
- * Status: Working, however there are 150ns idle
- * timeafter every 2 (16 bit or 4(8 bit) bus cycles
- */
-static void p_nand_lbd_write(u16 col_addr, u32 row_addr, u16 count, void *buff)
-{
- uint16_t w32cnt;
- uint16_t remainder;
- uint8_t *ptr8;
- uint16_t *ptr16;
- uint32_t *ptr32;
-
- remainder = count & 03;
- w32cnt = count >> 2;
- ptr32 = buff;
- ptr8 = buff;
-
- /*
- * send: CMDB1, CA0,CA1,RA0,RA1,RA2
- */
- nand_cmd_n_addr(PGMPAGE_B1, col_addr, row_addr);
-
- /*
- * blast the data out in 32bit chunks
- */
- while (w32cnt--)
- IOWR32(ndata_reg_vma, *ptr32++);
-
- /*
- * do the reminder if there is one
- * same handling for both 8 & 16 bit pnand: mode
- */
- ptr16 = (uint16_t *)ptr32; /* do 1 or 2 words */
-
- switch (remainder) {
- case 1:
- /*
- * read one 16 bit word
- */
- case 2:
- IOWR16(ndata_reg_vma, *ptr16);
- break;
-
- case 3:
- /*
- * for 3 bytes read 2 16 bit words
- */
- IOWR16(ndata_reg_vma, *ptr16++);
- IOWR16(ndata_reg_vma, *ptr16);
- break;
- default:
- /*
- * reminder is 0
- */
- break;
- }
- /*
- * finally issue a PGM cmd
- */
- IOWR8(ncmd_reg_vma, PGMPAGE_B2);
-}
-
-/*
- * write Astoria register
- */
-static inline void ast_p_nand_casdi_write(u8 reg_addr8, u16 data)
-{
- unsigned long flags;
- u16 addr16;
- /*
- * throw an error if called from multiple threads
- */
- static atomic_t rdreg_usage_cnt = { 0 };
-
- /*
- * disable interrupts
- */
- local_irq_save(flags);
-
- if (atomic_read(&rdreg_usage_cnt) != 0) {
- cy_as_hal_print_message(KERN_ERR "cy_as_omap_hal:"
- "* cy_as_hal_write_register usage:%d\n",
- atomic_read(&rdreg_usage_cnt));
- }
-
- atomic_inc(&rdreg_usage_cnt);
-
- /*
- * 2 flavors of GPMC -> PNAND access
- */
- if (pnand_16bit) {
- /*
- * 16 BIT gpmc NAND mode
- */
-
- /*
- * CMD1, CA1, CA2,
- */
- IOWR8(ncmd_reg_vma, 0x85);
- IOWR8(naddr_reg_vma, reg_addr8);
- IOWR8(naddr_reg_vma, 0x0c);
-
- /*
- * this should be sent on the 16 bit bus
- */
- IOWR16(ndata_reg_vma, data);
- } else {
- /*
- * 8 bit nand mode GPMC will automatically
- * seriallize 16bit or 32 bit writes into
- * 8 bit onesto the lower 8 bit in LE order
- */
- addr16 = 0x0c00 | reg_addr8;
-
- /*
- * CMD1, CA1, CA2,
- */
- IOWR8(ncmd_reg_vma, 0x85);
- IOWR16(naddr_reg_vma, addr16);
- IOWR16(ndata_reg_vma, data);
- }
-
- /*
- * re-enable interrupts
- */
- atomic_dec(&rdreg_usage_cnt);
- local_irq_restore(flags);
-}
-
-
-/*
- * read astoria register via pNAND interface
- */
-static inline u16 ast_p_nand_casdo_read(u8 reg_addr8)
-{
- u16 data;
- u16 addr16;
- unsigned long flags;
- /*
- * throw an error if called from multiple threads
- */
- static atomic_t wrreg_usage_cnt = { 0 };
-
- /*
- * disable interrupts
- */
- local_irq_save(flags);
-
- if (atomic_read(&wrreg_usage_cnt) != 0) {
- /*
- * if it gets here ( from other threads), this function needs
- * need spin_lock_irq save() protection
- */
- cy_as_hal_print_message(KERN_ERR"cy_as_omap_hal: "
- "cy_as_hal_write_register usage:%d\n",
- atomic_read(&wrreg_usage_cnt));
- }
- atomic_inc(&wrreg_usage_cnt);
-
- /*
- * 2 flavors of GPMC -> PNAND access
- */
- if (pnand_16bit) {
- /*
- * 16 BIT gpmc NAND mode
- * CMD1, CA1, CA2,
- */
-
- IOWR8(ncmd_reg_vma, 0x05);
- IOWR8(naddr_reg_vma, reg_addr8);
- IOWR8(naddr_reg_vma, 0x0c);
- IOWR8(ncmd_reg_vma, 0x00E0);
-
- udelay(1);
-
- /*
- * much faster through the gPMC Register space
- */
- data = IORD16(ndata_reg_vma);
- } else {
- /*
- * 8 BIT gpmc NAND mode
- * CMD1, CA1, CA2, CMD2
- */
- addr16 = 0x0c00 | reg_addr8;
- IOWR8(ncmd_reg_vma, 0x05);
- IOWR16(naddr_reg_vma, addr16);
- IOWR8(ncmd_reg_vma, 0xE0);
- udelay(1);
- data = IORD16(ndata_reg_vma);
- }
-
- /*
- * re-enable interrupts
- */
- atomic_dec(&wrreg_usage_cnt);
- local_irq_restore(flags);
-
- return data;
-}
-
-
-/*
- * This function must be defined to write a register within the WestBridge
- * device. The addr value is the address of the register to write with
- * respect to the base address of the WestBridge device.
- */
-void cy_as_hal_write_register(
- cy_as_hal_device_tag tag,
- uint16_t addr, uint16_t data)
-{
- ast_p_nand_casdi_write((u8)addr, data);
-}
-
-/*
- * This function must be defined to read a register from the WestBridge
- * device. The addr value is the address of the register to read with
- * respect to the base address of the WestBridge device.
- */
-uint16_t cy_as_hal_read_register(cy_as_hal_device_tag tag, uint16_t addr)
-{
- uint16_t data = 0;
-
- /*
- * READ ASTORIA REGISTER USING CASDO
- */
- data = ast_p_nand_casdo_read((u8)addr);
-
- return data;
-}
-
-/*
- * preps Ep pointers & data counters for next packet
- * (fragment of the request) xfer returns true if
- * there is a next transfer, and false if all bytes in
- * current request have been xfered
- */
-static inline bool prep_for_next_xfer(cy_as_hal_device_tag tag, uint8_t ep)
-{
-
- if (!end_points[ep].sg_list_enabled) {
- /*
- * no further transfers for non storage EPs
- * (like EP2 during firmware download, done
- * in 64 byte chunks)
- */
- if (end_points[ep].req_xfer_cnt >= end_points[ep].req_length) {
- DBGPRN("<1> %s():RQ sz:%d non-_sg EP:%d completed\n",
- __func__, end_points[ep].req_length, ep);
-
- /*
- * no more transfers, we are done with the request
- */
- return false;
- }
-
- /*
- * calculate size of the next DMA xfer, corner
- * case for non-storage EPs where transfer size
- * is not egual N * HAL_DMA_PKT_SZ xfers
- */
- if ((end_points[ep].req_length - end_points[ep].req_xfer_cnt)
- >= HAL_DMA_PKT_SZ) {
- end_points[ep].dma_xfer_sz = HAL_DMA_PKT_SZ;
- } else {
- /*
- * that would be the last chunk less
- * than P-port max size
- */
- end_points[ep].dma_xfer_sz = end_points[ep].req_length -
- end_points[ep].req_xfer_cnt;
- }
-
- return true;
- }
-
- /*
- * for SG_list assisted dma xfers
- * are we done with current SG ?
- */
- if (end_points[ep].seg_xfer_cnt == end_points[ep].sg_p->length) {
- /*
- * was it the Last SG segment on the list ?
- */
- if (sg_is_last(end_points[ep].sg_p)) {
- DBGPRN("<1> %s: EP:%d completed,"
- "%d bytes xfered\n",
- __func__,
- ep,
- end_points[ep].req_xfer_cnt
- );
-
- return false;
- } else {
- /*
- * There are more SG segments in current
- * request's sg list setup new segment
- */
-
- end_points[ep].seg_xfer_cnt = 0;
- end_points[ep].sg_p = sg_next(end_points[ep].sg_p);
- /* set data pointer for next DMA sg transfer*/
- end_points[ep].data_p = sg_virt(end_points[ep].sg_p);
- DBGPRN("<1> %s new SG:_va:%p\n\n",
- __func__, end_points[ep].data_p);
- }
-
- }
-
- /*
- * for sg list xfers it will always be 512 or 1024
- */
- end_points[ep].dma_xfer_sz = HAL_DMA_PKT_SZ;
-
- /*
- * next transfer is required
- */
-
- return true;
-}
-
-/*
- * Astoria DMA read request, APP_CPU reads from WB ep buffer
- */
-static void cy_service_e_p_dma_read_request(
- cy_as_omap_dev_kernel *dev_p, uint8_t ep)
-{
- cy_as_hal_device_tag tag = (cy_as_hal_device_tag)dev_p;
- uint16_t v, size;
- void *dptr;
- uint16_t col_addr = 0x0000;
- uint32_t row_addr = CYAS_DEV_CALC_EP_ADDR(ep);
- uint16_t ep_dma_reg = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2;
-
- /*
- * get the XFER size frtom WB eP DMA REGISTER
- */
- v = cy_as_hal_read_register(tag, ep_dma_reg);
-
- /*
- * amount of data in EP buff in bytes
- */
- size = v & CY_AS_MEM_P0_E_pn_DMA_REG_COUNT_MASK;
-
- /*
- * memory pointer for this DMA packet xfer (sub_segment)
- */
- dptr = end_points[ep].data_p;
-
- DBGPRN("<1>HAL:_svc_dma_read on EP_%d sz:%d, intr_seq:%d, dptr:%p\n",
- ep,
- size,
- intr_sequence_num,
- dptr
- );
-
- cy_as_hal_assert(size != 0);
-
- if (size) {
- /*
- * the actual WB-->OMAP memory "soft" DMA xfer
- */
- p_nand_lbd_read(col_addr, row_addr, size, dptr);
- }
-
- /*
- * clear DMAVALID bit indicating that the data has been read
- */
- cy_as_hal_write_register(tag, ep_dma_reg, 0);
-
- end_points[ep].seg_xfer_cnt += size;
- end_points[ep].req_xfer_cnt += size;
-
- /*
- * pre-advance data pointer (if it's outside sg
- * list it will be reset anyway
- */
- end_points[ep].data_p += size;
-
- if (prep_for_next_xfer(tag, ep)) {
- /*
- * we have more data to read in this request,
- * setup next dma packet due tell WB how much
- * data we are going to xfer next
- */
- v = end_points[ep].dma_xfer_sz/*HAL_DMA_PKT_SZ*/ |
- CY_AS_MEM_P0_E_pn_DMA_REG_DMAVAL;
- cy_as_hal_write_register(tag, ep_dma_reg, v);
- } else {
- end_points[ep].pending = cy_false;
- end_points[ep].type = cy_as_hal_none;
- end_points[ep].buffer_valid = cy_false;
-
- /*
- * notify the API that we are done with rq on this EP
- */
- if (callback) {
- DBGPRN("<1>trigg rd_dma completion cb: xfer_sz:%d\n",
- end_points[ep].req_xfer_cnt);
- callback(tag, ep,
- end_points[ep].req_xfer_cnt,
- CY_AS_ERROR_SUCCESS);
- }
- }
-}
-
-/*
- * omap_cpu needs to transfer data to ASTORIA EP buffer
- */
-static void cy_service_e_p_dma_write_request(
- cy_as_omap_dev_kernel *dev_p, uint8_t ep)
-{
- uint16_t addr;
- uint16_t v = 0;
- uint32_t size;
- uint16_t col_addr = 0x0000;
- uint32_t row_addr = CYAS_DEV_CALC_EP_ADDR(ep);
- void *dptr;
-
- cy_as_hal_device_tag tag = (cy_as_hal_device_tag)dev_p;
- /*
- * note: size here its the size of the dma transfer could be
- * anything > 0 && < P_PORT packet size
- */
- size = end_points[ep].dma_xfer_sz;
- dptr = end_points[ep].data_p;
-
- /*
- * perform the soft DMA transfer, soft in this case
- */
- if (size)
- p_nand_lbd_write(col_addr, row_addr, size, dptr);
-
- end_points[ep].seg_xfer_cnt += size;
- end_points[ep].req_xfer_cnt += size;
- /*
- * pre-advance data pointer
- * (if it's outside sg list it will be reset anyway)
- */
- end_points[ep].data_p += size;
-
- /*
- * now clear DMAVAL bit to indicate we are done
- * transferring data and that the data can now be
- * sent via USB to the USB host, sent to storage,
- * or used internally.
- */
-
- addr = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2;
- cy_as_hal_write_register(tag, addr, size);
-
- /*
- * finally, tell the USB subsystem that the
- * data is gone and we can accept the
- * next request if one exists.
- */
- if (prep_for_next_xfer(tag, ep)) {
- /*
- * There is more data to go. Re-init the WestBridge DMA side
- */
- v = end_points[ep].dma_xfer_sz |
- CY_AS_MEM_P0_E_pn_DMA_REG_DMAVAL;
- cy_as_hal_write_register(tag, addr, v);
- } else {
-
- end_points[ep].pending = cy_false;
- end_points[ep].type = cy_as_hal_none;
- end_points[ep].buffer_valid = cy_false;
-
- /*
- * notify the API that we are done with rq on this EP
- */
- if (callback) {
- /*
- * this callback will wake up the process that might be
- * sleeping on the EP which data is being transferred
- */
- callback(tag, ep,
- end_points[ep].req_xfer_cnt,
- CY_AS_ERROR_SUCCESS);
- }
- }
-}
-
-/*
- * HANDLE DRQINT from Astoria (called in AS_Intr context
- */
-static void cy_handle_d_r_q_interrupt(cy_as_omap_dev_kernel *dev_p)
-{
- uint16_t v;
- static uint8_t service_ep = 2;
-
- /*
- * We've got DRQ INT, read DRQ STATUS Register */
- v = cy_as_hal_read_register((cy_as_hal_device_tag)dev_p,
- CY_AS_MEM_P0_DRQ);
-
- if (v == 0) {
-#ifndef WESTBRIDGE_NDEBUG
- cy_as_hal_print_message("stray DRQ interrupt detected\n");
-#endif
- return;
- }
-
- /*
- * Now, pick a given DMA request to handle, for now, we just
- * go round robin. Each bit position in the service_mask
- * represents an endpoint from EP2 to EP15. We rotate through
- * each of the endpoints to find one that needs to be serviced.
- */
- while ((v & (1 << service_ep)) == 0) {
-
- if (service_ep == 15)
- service_ep = 2;
- else
- service_ep++;
- }
-
- if (end_points[service_ep].type == cy_as_hal_write) {
- /*
- * handle DMA WRITE REQUEST: app_cpu will
- * write data into astoria EP buffer
- */
- cy_service_e_p_dma_write_request(dev_p, service_ep);
- } else if (end_points[service_ep].type == cy_as_hal_read) {
- /*
- * handle DMA READ REQUEST: cpu will
- * read EP buffer from Astoria
- */
- cy_service_e_p_dma_read_request(dev_p, service_ep);
- }
-#ifndef WESTBRIDGE_NDEBUG
- else
- cy_as_hal_print_message("cyashalomap:interrupt,"
- " w/o pending DMA job,"
- "-check DRQ_MASK logic\n");
-#endif
-
- /*
- * Now bump the EP ahead, so other endpoints get
- * a shot before the one we just serviced
- */
- if (end_points[service_ep].type == cy_as_hal_none) {
- if (service_ep == 15)
- service_ep = 2;
- else
- service_ep++;
- }
-
-}
-
-void cy_as_hal_dma_cancel_request(cy_as_hal_device_tag tag, uint8_t ep)
-{
- DBGPRN("cy_as_hal_dma_cancel_request on ep:%d", ep);
- if (end_points[ep].pending)
- cy_as_hal_write_register(tag,
- CY_AS_MEM_P0_EP2_DMA_REG + ep - 2, 0);
-
- end_points[ep].buffer_valid = cy_false;
- end_points[ep].type = cy_as_hal_none;
-}
-
-/*
- * enables/disables SG list assisted DMA xfers for the given EP
- * sg_list assisted XFERS can use physical addresses of mem pages in case if the
- * xfer is performed by a h/w DMA controller rather then the CPU on P port
- */
-void cy_as_hal_set_ep_dma_mode(uint8_t ep, bool sg_xfer_enabled)
-{
- end_points[ep].sg_list_enabled = sg_xfer_enabled;
- DBGPRN("<1> EP:%d sg_list assisted DMA mode set to = %d\n",
- ep, end_points[ep].sg_list_enabled);
-}
-EXPORT_SYMBOL(cy_as_hal_set_ep_dma_mode);
-
-/*
- * This function must be defined to transfer a block of data to
- * the WestBridge device. This function can use the burst write
- * (DMA) capabilities of WestBridge to do this, or it can just copy
- * the data using writes.
- */
-void cy_as_hal_dma_setup_write(cy_as_hal_device_tag tag,
- uint8_t ep, void *buf,
- uint32_t size, uint16_t maxsize)
-{
- uint32_t addr = 0;
- uint16_t v = 0;
-
- /*
- * Note: "size" is the actual request size
- * "maxsize" - is the P port fragment size
- * No EP0 or EP1 traffic should get here
- */
- cy_as_hal_assert(ep != 0 && ep != 1);
-
- /*
- * If this asserts, we have an ordering problem. Another DMA request
- * is coming down before the previous one has completed.
- */
- cy_as_hal_assert(end_points[ep].buffer_valid == cy_false);
- end_points[ep].buffer_valid = cy_true;
- end_points[ep].type = cy_as_hal_write;
- end_points[ep].pending = cy_true;
-
- /*
- * total length of the request
- */
- end_points[ep].req_length = size;
-
- if (size >= maxsize) {
- /*
- * set xfer size for very 1st DMA xfer operation
- * port max packet size ( typically 512 or 1024)
- */
- end_points[ep].dma_xfer_sz = maxsize;
- } else {
- /*
- * smaller xfers for non-storage EPs
- */
- end_points[ep].dma_xfer_sz = size;
- }
-
- /*
- * check the EP transfer mode uses sg_list rather then a memory buffer
- * block devices pass it to the HAL, so the hAL could get to the real
- * physical address for each segment and set up a DMA controller
- * hardware ( if there is one)
- */
- if (end_points[ep].sg_list_enabled) {
- /*
- * buf - pointer to the SG list
- * data_p - data pointer to the 1st DMA segment
- * seg_xfer_cnt - keeps track of N of bytes sent in current
- * sg_list segment
- * req_xfer_cnt - keeps track of the total N of bytes
- * transferred for the request
- */
- end_points[ep].sg_p = buf;
- end_points[ep].data_p = sg_virt(end_points[ep].sg_p);
- end_points[ep].seg_xfer_cnt = 0;
- end_points[ep].req_xfer_cnt = 0;
-
-#ifdef DBGPRN_DMA_SETUP_WR
- DBGPRN("cyasomaphal:%s: EP:%d, buf:%p, buf_va:%p,"
- "req_sz:%d, maxsz:%d\n",
- __func__,
- ep,
- buf,
- end_points[ep].data_p,
- size,
- maxsize);
-#endif
-
- } else {
- /*
- * setup XFER for non sg_list assisted EPs
- */
-
- #ifdef DBGPRN_DMA_SETUP_WR
- DBGPRN("<1>%s non storage or sz < 512:"
- "EP:%d, sz:%d\n", __func__, ep, size);
- #endif
-
- end_points[ep].sg_p = NULL;
-
- /*
- * must be a VMA of a membuf in kernel space
- */
- end_points[ep].data_p = buf;
-
- /*
- * will keep track No of bytes xferred for the request
- */
- end_points[ep].req_xfer_cnt = 0;
- }
-
- /*
- * Tell WB we are ready to send data on the given endpoint
- */
- v = (end_points[ep].dma_xfer_sz & CY_AS_MEM_P0_E_pn_DMA_REG_COUNT_MASK)
- | CY_AS_MEM_P0_E_pn_DMA_REG_DMAVAL;
-
- addr = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2;
-
- cy_as_hal_write_register(tag, addr, v);
-}
-
-/*
- * This function must be defined to transfer a block of data from
- * the WestBridge device. This function can use the burst read
- * (DMA) capabilities of WestBridge to do this, or it can just
- * copy the data using reads.
- */
-void cy_as_hal_dma_setup_read(cy_as_hal_device_tag tag,
- uint8_t ep, void *buf,
- uint32_t size, uint16_t maxsize)
-{
- uint32_t addr;
- uint16_t v;
-
- /*
- * Note: "size" is the actual request size
- * "maxsize" - is the P port fragment size
- * No EP0 or EP1 traffic should get here
- */
- cy_as_hal_assert(ep != 0 && ep != 1);
-
- /*
- * If this asserts, we have an ordering problem.
- * Another DMA request is coming down before the
- * previous one has completed. we should not get
- * new requests if current is still in process
- */
-
- cy_as_hal_assert(end_points[ep].buffer_valid == cy_false);
-
- end_points[ep].buffer_valid = cy_true;
- end_points[ep].type = cy_as_hal_read;
- end_points[ep].pending = cy_true;
- end_points[ep].req_xfer_cnt = 0;
- end_points[ep].req_length = size;
-
- if (size >= maxsize) {
- /*
- * set xfer size for very 1st DMA xfer operation
- * port max packet size ( typically 512 or 1024)
- */
- end_points[ep].dma_xfer_sz = maxsize;
- } else {
- /*
- * so that we could handle small xfers on in case
- * of non-storage EPs
- */
- end_points[ep].dma_xfer_sz = size;
- }
-
- addr = CY_AS_MEM_P0_EP2_DMA_REG + ep - 2;
-
- if (end_points[ep].sg_list_enabled) {
- /*
- * Handle sg-list assisted EPs
- * seg_xfer_cnt - keeps track of N of sent packets
- * buf - pointer to the SG list
- * data_p - data pointer for the 1st DMA segment
- */
- end_points[ep].seg_xfer_cnt = 0;
- end_points[ep].sg_p = buf;
- end_points[ep].data_p = sg_virt(end_points[ep].sg_p);
-
- #ifdef DBGPRN_DMA_SETUP_RD
- DBGPRN("cyasomaphal:DMA_setup_read sg_list EP:%d, "
- "buf:%p, buf_va:%p, req_sz:%d, maxsz:%d\n",
- ep,
- buf,
- end_points[ep].data_p,
- size,
- maxsize);
- #endif
- v = (end_points[ep].dma_xfer_sz &
- CY_AS_MEM_P0_E_pn_DMA_REG_COUNT_MASK) |
- CY_AS_MEM_P0_E_pn_DMA_REG_DMAVAL;
- cy_as_hal_write_register(tag, addr, v);
- } else {
- /*
- * Non sg list EP passed void *buf rather then scatterlist *sg
- */
- #ifdef DBGPRN_DMA_SETUP_RD
- DBGPRN("%s:non-sg_list EP:%d,"
- "RQ_sz:%d, maxsz:%d\n",
- __func__, ep, size, maxsize);
- #endif
-
- end_points[ep].sg_p = NULL;
-
- /*
- * must be a VMA of a membuf in kernel space
- */
- end_points[ep].data_p = buf;
-
- /*
- * Program the EP DMA register for Storage endpoints only.
- */
- if (is_storage_e_p(ep)) {
- v = (end_points[ep].dma_xfer_sz &
- CY_AS_MEM_P0_E_pn_DMA_REG_COUNT_MASK) |
- CY_AS_MEM_P0_E_pn_DMA_REG_DMAVAL;
- cy_as_hal_write_register(tag, addr, v);
- }
- }
-}
-
-/*
- * This function must be defined to allow the WB API to
- * register a callback function that is called when a
- * DMA transfer is complete.
- */
-void cy_as_hal_dma_register_callback(cy_as_hal_device_tag tag,
- cy_as_hal_dma_complete_callback cb)
-{
- DBGPRN("<1>\n%s: WB API has registered a dma_complete callback:%x\n",
- __func__, (uint32_t)cb);
- callback = cb;
-}
-
-/*
- * This function must be defined to return the maximum size of
- * DMA request that can be handled on the given endpoint. The
- * return value should be the maximum size in bytes that the DMA
- * module can handle.
- */
-uint32_t cy_as_hal_dma_max_request_size(cy_as_hal_device_tag tag,
- cy_as_end_point_number_t ep)
-{
- /*
- * Storage reads and writes are always done in 512 byte blocks.
- * So, we do the count handling within the HAL, and save on
- * some of the data transfer delay.
- */
- if ((ep == CYASSTORAGE_READ_EP_NUM) ||
- (ep == CYASSTORAGE_WRITE_EP_NUM)) {
- /* max DMA request size HAL can handle by itself */
- return CYASSTORAGE_MAX_XFER_SIZE;
- } else {
- /*
- * For the USB - Processor endpoints, the maximum transfer
- * size depends on the speed of USB operation. So, we use
- * the following constant to indicate to the API that
- * splitting of the data into chunks less that or equal to
- * the max transfer size should be handled internally.
- */
-
- /* DEFINED AS 0xffffffff in cyasdma.h */
- return CY_AS_DMA_MAX_SIZE_HW_SIZE;
- }
-}
-
-/*
- * This function must be defined to set the state of the WAKEUP pin
- * on the WestBridge device. Generally this is done via a GPIO of
- * some type.
- */
-cy_bool cy_as_hal_set_wakeup_pin(cy_as_hal_device_tag tag, cy_bool state)
-{
- /*
- * Not supported as of now.
- */
- return cy_false;
-}
-
-void cy_as_hal_pll_lock_loss_handler(cy_as_hal_device_tag tag)
-{
- cy_as_hal_print_message("error: astoria PLL lock is lost\n");
- cy_as_hal_print_message("please check the input voltage levels");
- cy_as_hal_print_message("and clock, and restart the system\n");
-}
-
-/*
- * Below are the functions that must be defined to provide the basic
- * operating system services required by the API.
- */
-
-/*
- * This function is required by the API to allocate memory.
- * This function is expected to work exactly like malloc().
- */
-void *cy_as_hal_alloc(uint32_t cnt)
-{
- return kmalloc(cnt, GFP_ATOMIC);
-}
-
-/*
- * This function is required by the API to free memory allocated
- * with CyAsHalAlloc(). This function is'expected to work exacly
- * like free().
- */
-void cy_as_hal_free(void *mem_p)
-{
- kfree(mem_p);
-}
-
-/*
- * Allocator that can be used in interrupt context.
- * We have to ensure that the kmalloc call does not
- * sleep in this case.
- */
-void *cy_as_hal_c_b_alloc(uint32_t cnt)
-{
- return kmalloc(cnt, GFP_ATOMIC);
-}
-
-/*
- * This function is required to set a block of memory to a
- * specific value. This function is expected to work exactly
- * like memset()
- */
-void cy_as_hal_mem_set(void *ptr, uint8_t value, uint32_t cnt)
-{
- memset(ptr, value, cnt);
-}
-
-/*
- * This function is expected to create a sleep channel.
- * The data structure that represents the sleep channel object
- * sleep channel (which is Linux "wait_queue_head_t wq" for this particular HAL)
- * passed as a pointer, and allpocated by the caller
- * (typically as a local var on the stack) "Create" word should read as
- * "SleepOn", this func doesn't actually create anything
- */
-cy_bool cy_as_hal_create_sleep_channel(cy_as_hal_sleep_channel *channel)
-{
- init_waitqueue_head(&channel->wq);
- return cy_true;
-}
-
-/*
- * for this particular HAL it doesn't actually destroy anything
- * since no actual sleep object is created in CreateSleepChannel()
- * sleep channel is given by the pointer in the argument.
- */
-cy_bool cy_as_hal_destroy_sleep_channel(cy_as_hal_sleep_channel *channel)
-{
- return cy_true;
-}
-
-/*
- * platform specific wakeable Sleep implementation
- */
-cy_bool cy_as_hal_sleep_on(cy_as_hal_sleep_channel *channel, uint32_t ms)
-{
- wait_event_interruptible_timeout(channel->wq, 0, ((ms * HZ)/1000));
- return cy_true;
-}
-
-/*
- * wakes up the process waiting on the CHANNEL
- */
-cy_bool cy_as_hal_wake(cy_as_hal_sleep_channel *channel)
-{
- wake_up_interruptible_all(&channel->wq);
- return cy_true;
-}
-
-uint32_t cy_as_hal_disable_interrupts()
-{
- if (0 == intr__enable)
- ;
-
- intr__enable++;
- return 0;
-}
-
-void cy_as_hal_enable_interrupts(uint32_t val)
-{
- intr__enable--;
- if (0 == intr__enable)
- ;
-}
-
-/*
- * Sleep atleast 150ns, cpu dependent
- */
-void cy_as_hal_sleep150(void)
-{
- uint32_t i, j;
-
- j = 0;
- for (i = 0; i < 1000; i++)
- j += (~i);
-}
-
-void cy_as_hal_sleep(uint32_t ms)
-{
- cy_as_hal_sleep_channel channel;
-
- cy_as_hal_create_sleep_channel(&channel);
- cy_as_hal_sleep_on(&channel, ms);
- cy_as_hal_destroy_sleep_channel(&channel);
-}
-
-cy_bool cy_as_hal_is_polling()
-{
- return cy_false;
-}
-
-void cy_as_hal_c_b_free(void *ptr)
-{
- cy_as_hal_free(ptr);
-}
-
-/*
- * suppose to reinstate the astoria registers
- * that may be clobbered in sleep mode
- */
-void cy_as_hal_init_dev_registers(cy_as_hal_device_tag tag,
- cy_bool is_standby_wakeup)
-{
- /* specific to SPI, no implementation required */
- (void) tag;
- (void) is_standby_wakeup;
-}
-
-void cy_as_hal_read_regs_before_standby(cy_as_hal_device_tag tag)
-{
- /* specific to SPI, no implementation required */
- (void) tag;
-}
-
-cy_bool cy_as_hal_sync_device_clocks(cy_as_hal_device_tag tag)
-{
- /*
- * we are in asynchronous mode. so no need to handle this
- */
- return true;
-}
-
-/*
- * init OMAP h/w resources
- */
-int start_o_m_a_p_kernel(const char *pgm,
- cy_as_hal_device_tag *tag, cy_bool debug)
-{
- cy_as_omap_dev_kernel *dev_p;
- int i;
- u16 data16[4];
- u8 pncfg_reg;
-
- /*
- * No debug mode support through argument as of now
- */
- (void)debug;
-
- DBGPRN(KERN_INFO"starting OMAP34xx HAL...\n");
-
- /*
- * Initialize the HAL level endpoint DMA data.
- */
- for (i = 0; i < sizeof(end_points)/sizeof(end_points[0]); i++) {
- end_points[i].data_p = 0;
- end_points[i].pending = cy_false;
- end_points[i].size = 0;
- end_points[i].type = cy_as_hal_none;
- end_points[i].sg_list_enabled = cy_false;
-
- /*
- * by default the DMA transfers to/from the E_ps don't
- * use sg_list that implies that the upper devices like
- * blockdevice have to enable it for the E_ps in their
- * initialization code
- */
- }
-
- /*
- * allocate memory for OMAP HAL
- */
- dev_p = (cy_as_omap_dev_kernel *)cy_as_hal_alloc(
- sizeof(cy_as_omap_dev_kernel));
- if (dev_p == 0) {
- cy_as_hal_print_message("out of memory allocating OMAP"
- "device structure\n");
- return 0;
- }
-
- dev_p->m_sig = CY_AS_OMAP_KERNEL_HAL_SIG;
-
- /*
- * initialize OMAP hardware and StartOMAPKernelall gpio pins
- */
- dev_p->m_addr_base = (void *)cy_as_hal_processor_hw_init();
-
- /*
- * Now perform a hard reset of the device to have
- * the new settings take effect
- */
- __gpio_set_value(AST_WAKEUP, 1);
-
- /*
- * do Astoria h/w reset
- */
- DBGPRN(KERN_INFO"-_-_pulse -> westbridge RST pin\n");
-
- /*
- * NEGATIVE PULSE on RST pin
- */
- __gpio_set_value(AST_RESET, 0);
- mdelay(1);
- __gpio_set_value(AST_RESET, 1);
- mdelay(50);
-
- /*
- * note AFTER reset PNAND interface is 8 bit mode
- * so if gpmc Is configured in 8 bit mode upper half will be FF
- */
- pncfg_reg = ast_p_nand_casdo_read(CY_AS_MEM_PNAND_CFG);
-
-#ifdef PNAND_16BIT_MODE
-
- /*
- * switch to 16 bit mode, force NON-LNA LBD mode, 3 RA addr bytes
- */
- ast_p_nand_casdi_write(CY_AS_MEM_PNAND_CFG, 0x0001);
-
- /*
- * now in order to continue to talk to astoria
- * sw OMAP GPMC into 16 bit mode as well
- */
- cy_as_hal_gpmc_enable_16bit_bus(cy_true);
-#else
- /* Astoria and GPMC are already in 8 bit mode, just initialize PNAND_CFG */
- ast_p_nand_casdi_write(CY_AS_MEM_PNAND_CFG, 0x0000);
-#endif
-
- /*
- * NOTE: if you want to capture bus activity on the LA,
- * don't use printks in between the activities you want to capture.
- * prinks may take milliseconds, and the data of interest
- * will fall outside the LA capture window/buffer
- */
- data16[0] = ast_p_nand_casdo_read(CY_AS_MEM_CM_WB_CFG_ID);
- data16[1] = ast_p_nand_casdo_read(CY_AS_MEM_PNAND_CFG);
-
- if (data16[0] != 0xA200) {
- /*
- * astoria device is not found
- */
- printk(KERN_ERR "ERROR: astoria device is not found, CY_AS_MEM_CM_WB_CFG_ID ");
- printk(KERN_ERR "read returned:%4.4X: CY_AS_MEM_PNAND_CFG:%4.4x !\n",
- data16[0], data16[0]);
- goto bus_acc_error;
- }
-
- cy_as_hal_print_message(KERN_INFO" register access CASDO test:"
- "\n CY_AS_MEM_CM_WB_CFG_ID:%4.4x\n"
- "PNAND_CFG after RST:%4.4x\n "
- "CY_AS_MEM_PNAND_CFG"
- "after cfg_wr:%4.4x\n\n",
- data16[0], pncfg_reg, data16[1]);
-
- dev_p->thread_flag = 1;
- spin_lock_init(&int_lock);
- dev_p->m_next_p = m_omap_list_p;
-
- m_omap_list_p = dev_p;
- *tag = dev_p;
-
- cy_as_hal_configure_interrupts((void *)dev_p);
-
- cy_as_hal_print_message(KERN_INFO"OMAP3430__hal started tag:%p"
- ", kernel HZ:%d\n", dev_p, HZ);
-
- /*
- *make processor to storage endpoints SG assisted by default
- */
- cy_as_hal_set_ep_dma_mode(4, true);
- cy_as_hal_set_ep_dma_mode(8, true);
-
- return 1;
-
- /*
- * there's been a NAND bus access error or
- * astoria device is not connected
- */
-bus_acc_error:
- /*
- * at this point hal tag hasn't been set yet
- * so the device will not call omap_stop
- */
- cy_as_hal_omap_hardware_deinit(dev_p);
- cy_as_hal_free(dev_p);
- return 0;
-}
-
-#else
-/*
- * Some compilers do not like empty C files, so if the OMAP hal is not being
- * compiled, we compile this single function. We do this so that for a
- * given target HAL there are not multiple sources for the HAL functions.
- */
-void my_o_m_a_p_kernel_hal_dummy_function(void)
-{
-}
-
-#endif