/* * include/linux/hw_mutex.h * * GPL LICENSE SUMMARY * * Copyright(c) 2011-2013 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * 2200 Mission College Blvd. * Santa Clara, CA 97052 * * */ #ifndef LINUX_HW_MUTEX_H #define LINUX_HW_MUTEX_H #include #include #include #ifdef CONFIG_X86_PUMA6 /* For Puma-6 SoC */ /* 4 masters */ #define MASTER_TOTAL (4) #define HW_MUTEX_DEV_ID 0x0949 #endif #ifdef CONFIG_X86_PUMA7 /* For Puma-7 SoC */ /* 16 masters */ #define MASTER_TOTAL (16) #define HW_MUTEX_DEV_ID 0x2BE9 #endif /* HW MUTEX controller working mode */ typedef enum { HW_MUTEX_POLLING = 0, HW_MUTEX_FIFO_SCHE, HW_MUTEX_NULL_SCHE } hw_mutex_mode_type; #ifdef CONFIG_X86_PUMA6 /* Totally 4 masters are supported */ typedef enum { MASTER_ARM11 = 0, MASTER_PP = 1, MASTER_ATOM = 2, MASTER_RESV } hw_mutex_master_type; #endif #ifdef CONFIG_X86_PUMA7 /* Totally 16 masters are supported */ typedef enum { MASTER_ARM11 = 0, MASTER_BBU_C = 1, MASTER_ATOM = 2, MASTER_ARM9 = 3, MASTER_PHY_CPU = 4, MASTER_CSE = 5, MASTER_SEC = 6, MASTER_POLL0 = 7, /* use for polling */ MASTER_POLL1 = 8, /* use for polling */ MASTER_MOCA_C = 9, MASTER_RCE = 10, MASTER_RESV, MASTER_RESV1, MASTER_RESV2, MASTER_RESV3, MASTER_RESV4 } hw_mutex_master_type; #endif /* Devices use HW mutex */ typedef enum { HW_MUTEX_NOR_SPI = 0, HW_MUTEX_EMMC = 1, HW_MUTEX_ARM_MBX = 2, /* Mutex for protect the ARM Mbox Structure */ HW_MUTEX_ATOM_MBX = 3, /* Mutex for protect the ATOM Mbox Structure */ HW_MUTEX_GPIO = 4, /* Mutex for protect the GPIOs access */ HW_MUTEX_MAX_VAL } hw_mutex_device_type; /* 0: SPI_NOR_FLASH, 1: eMMC, 2,3: Mailbox*/ #define HW_MUTEX_TOTAL (HW_MUTEX_MAX_VAL) /* Each HW mutex is controlled by a software mutex */ struct hw_mutex { hw_mutex_device_type lock_name; spinlock_t irq_lock; struct mutex soft_lock; /* Causes a different thread to sleep waiting for the HW mutex */ struct mutex data_mutex; /* Protects the struct */ struct task_struct *owner; /* Which thread owns the MUTEX */ atomic_t status; /* 1: unlocked, 0: requesting, negative: locked, possible waiters */ unsigned int lock_count; /* Counts the number of lock/unlock calls. 0 = Unlocked */ #define HW_MUTEX_LOCKED (-1) /* The MUTEX is locked */ #define HW_MUTEX_REQUESTING (0) /* We've requested for the MUTEX, but not get it yet */ #define HW_MUTEX_UNLOCKED (1) /* The HW mutex is free */ #define HW_MUTEX_JAMMED (2) /* AVM: We took the HW mutex by force. */ }__attribute__((aligned(4))); struct hw_master { hw_mutex_master_type master; hw_mutex_mode_type mode; /* polling , fifo_interrupt, null_interrupt */ uint32_t irq_num; /* The irq number used for HW mutex */ void __iomem *reg_base; /* Mapped io reg base address */ struct pci_dev *dev; struct hw_mutex hw_mutexes[HW_MUTEX_TOTAL]; struct hw_mutex_operations *ops; bool use_sw_mutex_only; /* Indicates the NetIP driver is unavailable */ atomic_t dev_is_off; /* Indicates the HW Mutex is suspended or off, because of whether NetIP is off or on */ }__attribute__((aligned(4))); /* Abstraction oprations of a HW mutex */ struct hw_mutex_operations { char *name; void (*clr_intr)(struct hw_master* pmaster); int (*lock)(struct hw_mutex* hmutex, int force); void (*unlock)(struct hw_mutex* hmutex); uint8_t (*is_locked)(struct hw_mutex* hmutex); uint8_t (*is_waiting)(struct hw_mutex* hmutex); }__attribute__((aligned(4))); /* * hw_mutex_lock - acquire the mutex * @mutex: the mutex to be acquired * * Lock the mutex exclusively for this task. If the mutex is not * available right now, it will sleep until we can get it. * * The function is non interruptible */ extern void hw_mutex_lock(uint8_t mutex); /* * hw_mutex_lock_interruptible - acquire the mutex * @mutex: the mutex to be acquired * * Lock the mutex exclusively for this task. If the mutex is not * available right now, it will sleep until it can get it. * It can be interruptibed by signal, or exit when timeout * * Returns 0 if success, negative if interrupted or timeout */ extern long __must_check hw_mutex_lock_interruptible(uint8_t mutex); /* hw_mutex_is_locked - check whether the current master owns the mutex or not * @mutex: the mutex number to be checked * * Return 1, if current master owns the mutex * Return 0, if not * Return Negative for errors */ extern int __must_check hw_mutex_is_locked(uint8_t mutex); /* * hw_mutex_unlock - release the mutex * @mutex: the mutex to be released * * release the mutex got previously * */ extern void hw_mutex_unlock(uint8_t mutex); /* * hw_mutex_lock_test - lock as different master before acquiring the mutex * Then check if lock available to force the current master * to be kept on waitlist. Unlock as different master. * Now the current master should get the lock. * @mutex: the mutex to be acquired * * Lock the mutex exclusively for this task. If the mutex is not * available right now, it will sleep until we can get it. * * The function is non interruptible. * The function is exposed only if TEST_HWMUTEX is defined. */ #ifdef TEST_HWMUTEX extern void hw_mutex_lock_test(uint8_t mutex); #endif /* AVM */ #if defined(CONFIG_TFFS_PANIC_LOG) extern void hw_mutex_jam_lock(uint8_t mutex); #endif //#define HW_MUTEX_DEBUG 1 #ifdef HW_MUTEX_DEBUG //# define DEBUG_PRINT(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args) #define DEBUG_PRINT printk("\nLine %d.%s: ->\n",__LINE__,__FUNCTION__) #define DEBUG_PRINTK(fmt, args...) printk("%d@%s " fmt,__LINE__,__FUNCTION__ , ## args) #else #define DEBUG_PRINT do{} while (0) #define DEBUG_PRINTK(fmt, args...) do{} while (0) #endif #endif