1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/export.h>
4 #include <linux/pm_qos.h>
5 #include <linux/delay.h>
7 /* G-Min addition: "platform_is()" lives in intel_mid_pm.h in the MCG
8 * tree, but it's just platform ID info and we don't want to pull in
9 * the whole SFI-based PM architecture.
11 #define INTEL_ATOM_MRST 0x26
12 #define INTEL_ATOM_MFLD 0x27
13 #define INTEL_ATOM_CLV 0x35
14 #define INTEL_ATOM_MRFLD 0x4a
15 #define INTEL_ATOM_BYT 0x37
16 #define INTEL_ATOM_MOORFLD 0x5a
17 #define INTEL_ATOM_CHT 0x4c
18 /* synchronization for sharing the I2C controller */
19 #define PUNIT_PORT 0x04
20 #define PUNIT_DOORBELL_OPCODE (0xE0)
21 #define PUNIT_DOORBELL_REG (0x0)
22 #ifndef CSTATE_EXIT_LATENCY
23 #define CSTATE_EXIT_LATENCY_C1 1
25 static inline int platform_is(u8 model
)
27 return (boot_cpu_data
.x86_model
== model
);
30 #include "../../include/asm/intel_mid_pcihelpers.h"
32 /* Unified message bus read/write operation */
33 static DEFINE_SPINLOCK(msgbus_lock
);
35 static struct pci_dev
*pci_root
;
36 static struct pm_qos_request pm_qos
;
38 #define DW_I2C_NEED_QOS (platform_is(INTEL_ATOM_BYT))
40 static int intel_mid_msgbus_init(void)
42 pci_root
= pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
44 pr_err("%s: Error: msgbus PCI handle NULL\n", __func__
);
48 if (DW_I2C_NEED_QOS
) {
49 pm_qos_add_request(&pm_qos
,
50 PM_QOS_CPU_DMA_LATENCY
,
51 PM_QOS_DEFAULT_VALUE
);
55 fs_initcall(intel_mid_msgbus_init
);
57 u32
intel_mid_msgbus_read32_raw(u32 cmd
)
59 unsigned long irq_flags
;
62 spin_lock_irqsave(&msgbus_lock
, irq_flags
);
63 pci_write_config_dword(pci_root
, PCI_ROOT_MSGBUS_CTRL_REG
, cmd
);
64 pci_read_config_dword(pci_root
, PCI_ROOT_MSGBUS_DATA_REG
, &data
);
65 spin_unlock_irqrestore(&msgbus_lock
, irq_flags
);
69 EXPORT_SYMBOL(intel_mid_msgbus_read32_raw
);
72 * GU: this function is only used by the VISA and 'VXD' drivers.
74 u32
intel_mid_msgbus_read32_raw_ext(u32 cmd
, u32 cmd_ext
)
76 unsigned long irq_flags
;
79 spin_lock_irqsave(&msgbus_lock
, irq_flags
);
80 pci_write_config_dword(pci_root
, PCI_ROOT_MSGBUS_CTRL_EXT_REG
, cmd_ext
);
81 pci_write_config_dword(pci_root
, PCI_ROOT_MSGBUS_CTRL_REG
, cmd
);
82 pci_read_config_dword(pci_root
, PCI_ROOT_MSGBUS_DATA_REG
, &data
);
83 spin_unlock_irqrestore(&msgbus_lock
, irq_flags
);
87 EXPORT_SYMBOL(intel_mid_msgbus_read32_raw_ext
);
89 void intel_mid_msgbus_write32_raw(u32 cmd
, u32 data
)
91 unsigned long irq_flags
;
93 spin_lock_irqsave(&msgbus_lock
, irq_flags
);
94 pci_write_config_dword(pci_root
, PCI_ROOT_MSGBUS_DATA_REG
, data
);
95 pci_write_config_dword(pci_root
, PCI_ROOT_MSGBUS_CTRL_REG
, cmd
);
96 spin_unlock_irqrestore(&msgbus_lock
, irq_flags
);
98 EXPORT_SYMBOL(intel_mid_msgbus_write32_raw
);
101 * GU: this function is only used by the VISA and 'VXD' drivers.
103 void intel_mid_msgbus_write32_raw_ext(u32 cmd
, u32 cmd_ext
, u32 data
)
105 unsigned long irq_flags
;
107 spin_lock_irqsave(&msgbus_lock
, irq_flags
);
108 pci_write_config_dword(pci_root
, PCI_ROOT_MSGBUS_DATA_REG
, data
);
109 pci_write_config_dword(pci_root
, PCI_ROOT_MSGBUS_CTRL_EXT_REG
, cmd_ext
);
110 pci_write_config_dword(pci_root
, PCI_ROOT_MSGBUS_CTRL_REG
, cmd
);
111 spin_unlock_irqrestore(&msgbus_lock
, irq_flags
);
113 EXPORT_SYMBOL(intel_mid_msgbus_write32_raw_ext
);
115 u32
intel_mid_msgbus_read32(u8 port
, u32 addr
)
117 unsigned long irq_flags
;
122 cmd
= (PCI_ROOT_MSGBUS_READ
<< 24) | (port
<< 16) |
123 ((addr
& 0xff) << 8) | PCI_ROOT_MSGBUS_DWORD_ENABLE
;
124 cmdext
= addr
& 0xffffff00;
126 spin_lock_irqsave(&msgbus_lock
, irq_flags
);
129 /* This resets to 0 automatically, no need to write 0 */
130 pci_write_config_dword(pci_root
, PCI_ROOT_MSGBUS_CTRL_EXT_REG
,
134 pci_write_config_dword(pci_root
, PCI_ROOT_MSGBUS_CTRL_REG
, cmd
);
135 pci_read_config_dword(pci_root
, PCI_ROOT_MSGBUS_DATA_REG
, &data
);
136 spin_unlock_irqrestore(&msgbus_lock
, irq_flags
);
140 EXPORT_SYMBOL(intel_mid_msgbus_read32
);
142 void intel_mid_msgbus_write32(u8 port
, u32 addr
, u32 data
)
144 unsigned long irq_flags
;
148 cmd
= (PCI_ROOT_MSGBUS_WRITE
<< 24) | (port
<< 16) |
149 ((addr
& 0xFF) << 8) | PCI_ROOT_MSGBUS_DWORD_ENABLE
;
150 cmdext
= addr
& 0xffffff00;
152 spin_lock_irqsave(&msgbus_lock
, irq_flags
);
153 pci_write_config_dword(pci_root
, PCI_ROOT_MSGBUS_DATA_REG
, data
);
156 /* This resets to 0 automatically, no need to write 0 */
157 pci_write_config_dword(pci_root
, PCI_ROOT_MSGBUS_CTRL_EXT_REG
,
161 pci_write_config_dword(pci_root
, PCI_ROOT_MSGBUS_CTRL_REG
, cmd
);
162 spin_unlock_irqrestore(&msgbus_lock
, irq_flags
);
164 EXPORT_SYMBOL(intel_mid_msgbus_write32
);
166 /* called only from where is later then fs_initcall */
167 u32
intel_mid_soc_stepping(void)
169 return pci_root
->revision
;
171 EXPORT_SYMBOL(intel_mid_soc_stepping
);
173 static bool is_south_complex_device(struct pci_dev
*dev
)
175 unsigned int base_class
= dev
->class >> 16;
176 unsigned int sub_class
= (dev
->class & SUB_CLASS_MASK
) >> 8;
178 /* other than camera, pci bridges and display,
179 * everything else are south complex devices.
181 if (((base_class
== PCI_BASE_CLASS_MULTIMEDIA
) &&
182 (sub_class
== ISP_SUB_CLASS
)) ||
183 (base_class
== PCI_BASE_CLASS_BRIDGE
) ||
184 ((base_class
== PCI_BASE_CLASS_DISPLAY
) && !sub_class
))
190 /* In BYT platform, d3_delay for internal south complex devices,
191 * they are not subject to 10 ms d3 to d0 delay required by pci spec.
193 static void pci_d3_delay_fixup(struct pci_dev
*dev
)
195 if (platform_is(INTEL_ATOM_BYT
) ||
196 platform_is(INTEL_ATOM_CHT
)) {
197 /* All internal devices are in bus 0. */
198 if (dev
->bus
->number
== 0 && is_south_complex_device(dev
)) {
199 dev
->d3_delay
= INTERNAL_PCI_PM_D3_WAIT
;
200 dev
->d3cold_delay
= INTERNAL_PCI_PM_D3_WAIT
;
204 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL
, PCI_ANY_ID
, pci_d3_delay_fixup
);
206 #define PUNIT_SEMAPHORE (platform_is(INTEL_ATOM_BYT) ? 0x7 : 0x10E)
207 #define GET_SEM() (intel_mid_msgbus_read32(PUNIT_PORT, PUNIT_SEMAPHORE) & 0x1)
209 static void reset_semaphore(void)
213 data
= intel_mid_msgbus_read32(PUNIT_PORT
, PUNIT_SEMAPHORE
);
215 data
= data
& 0xfffffffc;
216 intel_mid_msgbus_write32(PUNIT_PORT
, PUNIT_SEMAPHORE
, data
);
221 int intel_mid_dw_i2c_acquire_ownership(void)
224 u32 data
= 0; /* data sent to PUNIT */
230 pm_qos_update_request(&pm_qos
, CSTATE_EXIT_LATENCY_C1
- 1);
233 * We need disable irq. Otherwise, the main thread
234 * might be preempted and the other thread jumps to
235 * disable irq for a long time. Another case is
236 * some irq handlers might trigger power voltage change
238 BUG_ON(irqs_disabled());
241 /* host driver writes 0x2 to side band register 0x7 */
242 intel_mid_msgbus_write32(PUNIT_PORT
, PUNIT_SEMAPHORE
, 0x2);
245 /* host driver sends 0xE0 opcode to PUNIT and writes 0 register */
246 cmd
= (PUNIT_DOORBELL_OPCODE
<< 24) | (PUNIT_PORT
<< 16) |
247 ((PUNIT_DOORBELL_REG
& 0xFF) << 8) | PCI_ROOT_MSGBUS_DWORD_ENABLE
;
248 cmdext
= PUNIT_DOORBELL_REG
& 0xffffff00;
251 intel_mid_msgbus_write32_raw_ext(cmd
, cmdext
, data
);
253 intel_mid_msgbus_write32_raw(cmd
, data
);
255 /* host driver waits for bit 0 to be set in side band 0x7 */
256 while (GET_SEM() != 0x1) {
260 pr_err("Timeout: semaphore timed out, reset sem\n");
263 /*Delay 1ms in case race with punit*/
265 if (GET_SEM() != 0) {
266 /*Reset again as kernel might race with punit*/
269 pr_err("PUNIT SEM: %d\n",
270 intel_mid_msgbus_read32(PUNIT_PORT
,
274 if (DW_I2C_NEED_QOS
) {
275 pm_qos_update_request(&pm_qos
,
276 PM_QOS_DEFAULT_VALUE
);
286 EXPORT_SYMBOL(intel_mid_dw_i2c_acquire_ownership
);
288 int intel_mid_dw_i2c_release_ownership(void)
294 pm_qos_update_request(&pm_qos
, PM_QOS_DEFAULT_VALUE
);
298 EXPORT_SYMBOL(intel_mid_dw_i2c_release_ownership
);