1 /* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. 2 * 3 * This program is free software; you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License version 2 and 5 * only version 2 as published by the Free Software Foundation. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 */ 12 13 #ifndef __MFD_TABLA_CORE_H__ 14 #define __MFD_TABLA_CORE_H__ 15 16 #include <linux/interrupt.h> 17 #include <linux/pm_qos.h> 18 19 #define WCD9XXX_NUM_IRQ_REGS 3 20 21 #define WCD9XXX_SLIM_NUM_PORT_REG 3 22 23 #define WCD9XXX_INTERFACE_TYPE_SLIMBUS 0x00 24 #define WCD9XXX_INTERFACE_TYPE_I2C 0x01 25 26 #define TABLA_VERSION_1_0 0 27 #define TABLA_VERSION_1_1 1 28 #define TABLA_VERSION_2_0 2 29 #define TABLA_IS_1_X(ver) \ 30 (((ver == TABLA_VERSION_1_0) || (ver == TABLA_VERSION_1_1)) ? 1 : 0) 31 #define TABLA_IS_2_0(ver) ((ver == TABLA_VERSION_2_0) ? 1 : 0) 32 33 #define SITAR_VERSION_1P0 0 34 #define SITAR_VERSION_1P1 1 35 #define SITAR_IS_1P0(ver) \ 36 ((ver == SITAR_VERSION_1P0) ? 1 : 0) 37 #define SITAR_IS_1P1(ver) \ 38 ((ver == SITAR_VERSION_1P1) ? 1 : 0) 39 40 enum { 41 TABLA_IRQ_SLIMBUS = 0, 42 TABLA_IRQ_MBHC_REMOVAL, 43 TABLA_IRQ_MBHC_SHORT_TERM, 44 TABLA_IRQ_MBHC_PRESS, 45 TABLA_IRQ_MBHC_RELEASE, 46 TABLA_IRQ_MBHC_POTENTIAL, 47 TABLA_IRQ_MBHC_INSERTION, 48 TABLA_IRQ_BG_PRECHARGE, 49 TABLA_IRQ_PA1_STARTUP, 50 TABLA_IRQ_PA2_STARTUP, 51 TABLA_IRQ_PA3_STARTUP, 52 TABLA_IRQ_PA4_STARTUP, 53 TABLA_IRQ_PA5_STARTUP, 54 TABLA_IRQ_MICBIAS1_PRECHARGE, 55 TABLA_IRQ_MICBIAS2_PRECHARGE, 56 TABLA_IRQ_MICBIAS3_PRECHARGE, 57 TABLA_IRQ_HPH_PA_OCPL_FAULT, 58 TABLA_IRQ_HPH_PA_OCPR_FAULT, 59 TABLA_IRQ_EAR_PA_OCPL_FAULT, 60 TABLA_IRQ_HPH_L_PA_STARTUP, 61 TABLA_IRQ_HPH_R_PA_STARTUP, 62 TABLA_IRQ_EAR_PA_STARTUP, 63 TABLA_NUM_IRQS, 64 }; 65 66 enum { 67 SITAR_IRQ_SLIMBUS = 0, 68 SITAR_IRQ_MBHC_REMOVAL, 69 SITAR_IRQ_MBHC_SHORT_TERM, 70 SITAR_IRQ_MBHC_PRESS, 71 SITAR_IRQ_MBHC_RELEASE, 72 SITAR_IRQ_MBHC_POTENTIAL, 73 SITAR_IRQ_MBHC_INSERTION, 74 SITAR_IRQ_BG_PRECHARGE, 75 SITAR_IRQ_PA1_STARTUP, 76 SITAR_IRQ_PA2_STARTUP, 77 SITAR_IRQ_PA3_STARTUP, 78 SITAR_IRQ_PA4_STARTUP, 79 SITAR_IRQ_PA5_STARTUP, 80 SITAR_IRQ_MICBIAS1_PRECHARGE, 81 SITAR_IRQ_MICBIAS2_PRECHARGE, 82 SITAR_IRQ_MICBIAS3_PRECHARGE, 83 SITAR_IRQ_HPH_PA_OCPL_FAULT, 84 SITAR_IRQ_HPH_PA_OCPR_FAULT, 85 SITAR_IRQ_EAR_PA_OCPL_FAULT, 86 SITAR_IRQ_HPH_L_PA_STARTUP, 87 SITAR_IRQ_HPH_R_PA_STARTUP, 88 SITAR_IRQ_EAR_PA_STARTUP, 89 SITAR_NUM_IRQS, 90 }; 91 92 93 enum { 94 TAIKO_IRQ_SLIMBUS = 0, 95 TAIKO_IRQ_MBHC_REMOVAL, 96 TAIKO_IRQ_MBHC_SHORT_TERM, 97 TAIKO_IRQ_MBHC_PRESS, 98 TAIKO_IRQ_MBHC_RELEASE, 99 TAIKO_IRQ_MBHC_POTENTIAL, 100 TAIKO_IRQ_MBHC_INSERTION, 101 TAIKO_IRQ_BG_PRECHARGE, 102 TAIKO_IRQ_PA1_STARTUP, 103 TAIKO_IRQ_PA2_STARTUP, 104 TAIKO_IRQ_PA3_STARTUP, 105 TAIKO_IRQ_PA4_STARTUP, 106 TAIKO_IRQ_PA5_STARTUP, 107 TAIKO_IRQ_MICBIAS1_PRECHARGE, 108 TAIKO_IRQ_MICBIAS2_PRECHARGE, 109 TAIKO_IRQ_MICBIAS3_PRECHARGE, 110 TAIKO_IRQ_HPH_PA_OCPL_FAULT, 111 TAIKO_IRQ_HPH_PA_OCPR_FAULT, 112 TAIKO_IRQ_EAR_PA_OCPL_FAULT, 113 TAIKO_IRQ_HPH_L_PA_STARTUP, 114 TAIKO_IRQ_HPH_R_PA_STARTUP, 115 TAIKO_IRQ_EAR_PA_STARTUP, 116 TAIKO_NUM_IRQS, 117 }; 118 119 enum wcd9xxx_pm_state { 120 WCD9XXX_PM_SLEEPABLE, 121 WCD9XXX_PM_AWAKE, 122 WCD9XXX_PM_ASLEEP, 123 }; 124 125 struct wcd9xxx { 126 struct device *dev; 127 struct slim_device *slim; 128 struct slim_device *slim_slave; 129 struct mutex io_lock; 130 struct mutex xfer_lock; 131 struct mutex irq_lock; 132 u8 version; 133 134 unsigned int irq_base; 135 unsigned int irq; 136 u8 irq_masks_cur[WCD9XXX_NUM_IRQ_REGS]; 137 u8 irq_masks_cache[WCD9XXX_NUM_IRQ_REGS]; 138 u8 irq_level[WCD9XXX_NUM_IRQ_REGS]; 139 140 int reset_gpio; 141 142 int (*read_dev)(struct wcd9xxx *wcd9xxx, unsigned short reg, 143 int bytes, void *dest, bool interface_reg); 144 int (*write_dev)(struct wcd9xxx *wcd9xxx, unsigned short reg, 145 int bytes, void *src, bool interface_reg); 146 147 u32 num_of_supplies; 148 struct regulator_bulk_data *supplies; 149 150 enum wcd9xxx_pm_state pm_state; 151 struct mutex pm_lock; 152 /* pm_wq notifies change of pm_state */ 153 wait_queue_head_t pm_wq; 154 struct pm_qos_request pm_qos_req; 155 int wlock_holders; 156 157 int num_rx_port; 158 int num_tx_port; 159 160 u8 idbyte[4]; 161 }; 162 163 int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg); 164 int wcd9xxx_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg, 165 u8 val); 166 int wcd9xxx_interface_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg); 167 int wcd9xxx_interface_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg, 168 u8 val); 169 int wcd9xxx_bulk_read(struct wcd9xxx *wcd9xxx, unsigned short reg, 170 int count, u8 *buf); 171 int wcd9xxx_bulk_write(struct wcd9xxx *wcd9xxx, unsigned short reg, 172 int count, u8 *buf); 173 int wcd9xxx_irq_init(struct wcd9xxx *wcd9xxx); 174 void wcd9xxx_irq_exit(struct wcd9xxx *wcd9xxx); 175 int wcd9xxx_get_logical_addresses(u8 *pgd_la, u8 *inf_la); 176 int wcd9xxx_get_intf_type(void); 177 178 bool wcd9xxx_lock_sleep(struct wcd9xxx *wcd9xxx); 179 void wcd9xxx_unlock_sleep(struct wcd9xxx *wcd9xxx); 180 enum wcd9xxx_pm_state wcd9xxx_pm_cmpxchg(struct wcd9xxx *wcd9xxx, 181 enum wcd9xxx_pm_state o, 182 enum wcd9xxx_pm_state n); 183 184 static inline int wcd9xxx_request_irq(struct wcd9xxx *wcd9xxx, int irq, 185 irq_handler_t handler, const char *name, 186 void *data) 187 { 188 if (!wcd9xxx->irq_base) 189 return -EINVAL; 190 return request_threaded_irq(wcd9xxx->irq_base + irq, NULL, handler, 191 IRQF_TRIGGER_RISING, name, 192 data); 193 } 194 static inline void wcd9xxx_free_irq(struct wcd9xxx *wcd9xxx, 195 int irq, void *data) 196 { 197 if (!wcd9xxx->irq_base) 198 return; 199 free_irq(wcd9xxx->irq_base + irq, data); 200 } 201 static inline void wcd9xxx_enable_irq(struct wcd9xxx *wcd9xxx, int irq) 202 { 203 if (!wcd9xxx->irq_base) 204 return; 205 enable_irq(wcd9xxx->irq_base + irq); 206 } 207 static inline void wcd9xxx_disable_irq(struct wcd9xxx *wcd9xxx, int irq) 208 { 209 if (!wcd9xxx->irq_base) 210 return; 211 disable_irq_nosync(wcd9xxx->irq_base + irq); 212 } 213 static inline void wcd9xxx_disable_irq_sync(struct wcd9xxx *wcd9xxx, int irq) 214 { 215 if (!wcd9xxx->irq_base) 216 return; 217 disable_irq(wcd9xxx->irq_base + irq); 218 } 219 220 #endif 221