1 #include <linux/export.h>
3 #include <linux/pm_qos.h>
4 #include <linux/delay.h>
6 /* G-Min addition: "platform_is()" lives in intel_mid_pm.h in the MCG
7 * tree, but it's just platform ID info and we don't want to pull in
8 * the whole SFI-based PM architecture. */
9 #define INTEL_ATOM_MRST 0x26
10 #define INTEL_ATOM_MFLD 0x27
11 #define INTEL_ATOM_CLV 0x35
12 #define INTEL_ATOM_MRFLD 0x4a
13 #define INTEL_ATOM_BYT 0x37
14 #define INTEL_ATOM_MOORFLD 0x5a
15 #define INTEL_ATOM_CHT 0x4c
16 /* synchronization for sharing the I2C controller */
17 #define PUNIT_PORT 0x04
18 #define PUNIT_DOORBELL_OPCODE (0xE0)
19 #define PUNIT_DOORBELL_REG (0x0)
20 #ifndef CSTATE_EXIT_LATENCY
21 #define CSTATE_EXIT_LATENCY_C1 1
23 static inline int platform_is(u8 model)
25 return (boot_cpu_data.x86_model == model);
28 #include "../../include/asm/intel_mid_pcihelpers.h"
30 /* Unified message bus read/write operation */
31 static DEFINE_SPINLOCK(msgbus_lock);
33 static struct pci_dev *pci_root;
34 static struct pm_qos_request pm_qos;
37 #define DW_I2C_NEED_QOS (platform_is(INTEL_ATOM_BYT))
39 static int intel_mid_msgbus_init(void)
41 pci_root = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
43 pr_err("%s: Error: msgbus PCI handle NULL\n", __func__);
47 if (DW_I2C_NEED_QOS) {
48 pm_qos_add_request(&pm_qos,
49 PM_QOS_CPU_DMA_LATENCY,
50 PM_QOS_DEFAULT_VALUE);
54 fs_initcall(intel_mid_msgbus_init);
56 u32 intel_mid_msgbus_read32_raw(u32 cmd)
58 unsigned long irq_flags;
61 spin_lock_irqsave(&msgbus_lock, irq_flags);
62 pci_write_config_dword(pci_root, PCI_ROOT_MSGBUS_CTRL_REG, cmd);
63 pci_read_config_dword(pci_root, PCI_ROOT_MSGBUS_DATA_REG, &data);
64 spin_unlock_irqrestore(&msgbus_lock, irq_flags);
68 EXPORT_SYMBOL(intel_mid_msgbus_read32_raw);
71 * GU: this function is only used by the VISA and 'VXD' drivers.
73 u32 intel_mid_msgbus_read32_raw_ext(u32 cmd, u32 cmd_ext)
75 unsigned long irq_flags;
78 spin_lock_irqsave(&msgbus_lock, irq_flags);
79 pci_write_config_dword(pci_root, PCI_ROOT_MSGBUS_CTRL_EXT_REG, cmd_ext);
80 pci_write_config_dword(pci_root, PCI_ROOT_MSGBUS_CTRL_REG, cmd);
81 pci_read_config_dword(pci_root, PCI_ROOT_MSGBUS_DATA_REG, &data);
82 spin_unlock_irqrestore(&msgbus_lock, irq_flags);
86 EXPORT_SYMBOL(intel_mid_msgbus_read32_raw_ext);
88 void intel_mid_msgbus_write32_raw(u32 cmd, u32 data)
90 unsigned long irq_flags;
92 spin_lock_irqsave(&msgbus_lock, irq_flags);
93 pci_write_config_dword(pci_root, PCI_ROOT_MSGBUS_DATA_REG, data);
94 pci_write_config_dword(pci_root, PCI_ROOT_MSGBUS_CTRL_REG, cmd);
95 spin_unlock_irqrestore(&msgbus_lock, irq_flags);
97 EXPORT_SYMBOL(intel_mid_msgbus_write32_raw);
100 * GU: this function is only used by the VISA and 'VXD' drivers.
102 void intel_mid_msgbus_write32_raw_ext(u32 cmd, u32 cmd_ext, u32 data)
104 unsigned long irq_flags;
106 spin_lock_irqsave(&msgbus_lock, irq_flags);
107 pci_write_config_dword(pci_root, PCI_ROOT_MSGBUS_DATA_REG, data);
108 pci_write_config_dword(pci_root, PCI_ROOT_MSGBUS_CTRL_EXT_REG, cmd_ext);
109 pci_write_config_dword(pci_root, PCI_ROOT_MSGBUS_CTRL_REG, cmd);
110 spin_unlock_irqrestore(&msgbus_lock, irq_flags);
112 EXPORT_SYMBOL(intel_mid_msgbus_write32_raw_ext);
114 u32 intel_mid_msgbus_read32(u8 port, u32 addr)
116 unsigned long irq_flags;
121 cmd = (PCI_ROOT_MSGBUS_READ << 24) | (port << 16) |
122 ((addr & 0xff) << 8) | PCI_ROOT_MSGBUS_DWORD_ENABLE;
123 cmdext = addr & 0xffffff00;
125 spin_lock_irqsave(&msgbus_lock, irq_flags);
128 /* This resets to 0 automatically, no need to write 0 */
129 pci_write_config_dword(pci_root, PCI_ROOT_MSGBUS_CTRL_EXT_REG,
133 pci_write_config_dword(pci_root, PCI_ROOT_MSGBUS_CTRL_REG, cmd);
134 pci_read_config_dword(pci_root, PCI_ROOT_MSGBUS_DATA_REG, &data);
135 spin_unlock_irqrestore(&msgbus_lock, irq_flags);
140 EXPORT_SYMBOL(intel_mid_msgbus_read32);
141 void intel_mid_msgbus_write32(u8 port, u32 addr, u32 data)
143 unsigned long irq_flags;
147 cmd = (PCI_ROOT_MSGBUS_WRITE << 24) | (port << 16) |
148 ((addr & 0xFF) << 8) | PCI_ROOT_MSGBUS_DWORD_ENABLE;
149 cmdext = addr & 0xffffff00;
151 spin_lock_irqsave(&msgbus_lock, irq_flags);
152 pci_write_config_dword(pci_root, PCI_ROOT_MSGBUS_DATA_REG, data);
155 /* This resets to 0 automatically, no need to write 0 */
156 pci_write_config_dword(pci_root, PCI_ROOT_MSGBUS_CTRL_EXT_REG,
160 pci_write_config_dword(pci_root, PCI_ROOT_MSGBUS_CTRL_REG, cmd);
161 spin_unlock_irqrestore(&msgbus_lock, irq_flags);
163 EXPORT_SYMBOL(intel_mid_msgbus_write32);
165 /* called only from where is later then fs_initcall */
166 u32 intel_mid_soc_stepping(void)
168 return pci_root->revision;
170 EXPORT_SYMBOL(intel_mid_soc_stepping);
172 static bool is_south_complex_device(struct pci_dev *dev)
174 unsigned base_class = dev->class >> 16;
175 unsigned sub_class = (dev->class & SUB_CLASS_MASK) >> 8;
177 /* other than camera, pci bridges and display,
178 * everything else are south complex devices.
180 if (((base_class == PCI_BASE_CLASS_MULTIMEDIA) &&
181 (sub_class == ISP_SUB_CLASS)) ||
182 (base_class == PCI_BASE_CLASS_BRIDGE) ||
183 ((base_class == PCI_BASE_CLASS_DISPLAY) && !sub_class))
189 /* In BYT platform, d3_delay for internal south complex devices,
190 * they are not subject to 10 ms d3 to d0 delay required by pci spec.
192 static void pci_d3_delay_fixup(struct pci_dev *dev)
194 if (platform_is(INTEL_ATOM_BYT) ||
195 platform_is(INTEL_ATOM_CHT)) {
196 /* All internal devices are in bus 0. */
197 if (dev->bus->number == 0 && is_south_complex_device(dev)) {
198 dev->d3_delay = INTERNAL_PCI_PM_D3_WAIT;
199 dev->d3cold_delay = INTERNAL_PCI_PM_D3_WAIT;
203 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_d3_delay_fixup);
205 #define PUNIT_SEMAPHORE (platform_is(INTEL_ATOM_BYT) ? 0x7 : 0x10E)
206 #define GET_SEM() (intel_mid_msgbus_read32(PUNIT_PORT, PUNIT_SEMAPHORE) & 0x1)
208 static void reset_semaphore(void)
212 data = intel_mid_msgbus_read32(PUNIT_PORT, PUNIT_SEMAPHORE);
214 data = data & 0xfffffffc;
215 intel_mid_msgbus_write32(PUNIT_PORT, PUNIT_SEMAPHORE, data);
220 int intel_mid_dw_i2c_acquire_ownership(void)
223 u32 data = 0; /* data sent to PUNIT */
229 pm_qos_update_request(&pm_qos, CSTATE_EXIT_LATENCY_C1 - 1);
232 * We need disable irq. Otherwise, the main thread
233 * might be preempted and the other thread jumps to
234 * disable irq for a long time. Another case is
235 * some irq handlers might trigger power voltage change
237 BUG_ON(irqs_disabled());
240 /* host driver writes 0x2 to side band register 0x7 */
241 intel_mid_msgbus_write32(PUNIT_PORT, PUNIT_SEMAPHORE, 0x2);
244 /* host driver sends 0xE0 opcode to PUNIT and writes 0 register */
245 cmd = (PUNIT_DOORBELL_OPCODE << 24) | (PUNIT_PORT << 16) |
246 ((PUNIT_DOORBELL_REG & 0xFF) << 8) | PCI_ROOT_MSGBUS_DWORD_ENABLE;
247 cmdext = PUNIT_DOORBELL_REG & 0xffffff00;
250 intel_mid_msgbus_write32_raw_ext(cmd, cmdext, data);
252 intel_mid_msgbus_write32_raw(cmd, data);
254 /* host driver waits for bit 0 to be set in side band 0x7 */
255 while (GET_SEM() != 0x1) {
259 pr_err("Timeout: semaphore timed out, reset sem\n");
262 /*Delay 1ms in case race with punit*/
264 if (GET_SEM() != 0) {
265 /*Reset again as kernel might race with punit*/
268 pr_err("PUNIT SEM: %d\n",
269 intel_mid_msgbus_read32(PUNIT_PORT,
273 if (DW_I2C_NEED_QOS) {
274 pm_qos_update_request(&pm_qos,
275 PM_QOS_DEFAULT_VALUE);
285 EXPORT_SYMBOL(intel_mid_dw_i2c_acquire_ownership);
287 int intel_mid_dw_i2c_release_ownership(void)
293 pm_qos_update_request(&pm_qos, PM_QOS_DEFAULT_VALUE);
297 EXPORT_SYMBOL(intel_mid_dw_i2c_release_ownership);