<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.dissonant.dev/index.php?action=history&amp;feed=atom&amp;title=Mainline%3ABroadcom_Kona%2FPower_Manager</id>
	<title>Mainline:Broadcom Kona/Power Manager - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.dissonant.dev/index.php?action=history&amp;feed=atom&amp;title=Mainline%3ABroadcom_Kona%2FPower_Manager"/>
	<link rel="alternate" type="text/html" href="https://wiki.dissonant.dev/index.php?title=Mainline:Broadcom_Kona/Power_Manager&amp;action=history"/>
	<updated>2026-04-15T02:37:47Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>https://wiki.dissonant.dev/index.php?title=Mainline:Broadcom_Kona/Power_Manager&amp;diff=27&amp;oldid=prev</id>
		<title>Knuxify: /* Initialization */</title>
		<link rel="alternate" type="text/html" href="https://wiki.dissonant.dev/index.php?title=Mainline:Broadcom_Kona/Power_Manager&amp;diff=27&amp;oldid=prev"/>
		<updated>2025-01-20T17:21:48Z</updated>

		<summary type="html">&lt;p&gt;&lt;span class=&quot;autocomment&quot;&gt;Initialization&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 19:21, 20 January 2025&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l40&quot;&gt;Line 40:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 40:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Next, the sequencer is disabled (&amp;lt;code&amp;gt;pwr_mgr_pm_i2c_enable(false)&amp;lt;/code&amp;gt; - [[#I2C_ENABLE_OFFSET - 0x4100]]) and initialized with the provided data (&amp;lt;code&amp;gt;pwr_mgr_init_sequencer(info);&amp;lt;/code&amp;gt;).&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Next, the sequencer is disabled (&amp;lt;code&amp;gt;pwr_mgr_pm_i2c_enable(false)&amp;lt;/code&amp;gt; - [[#I2C_ENABLE_OFFSET - 0x4100]]) and initialized with the provided data (&amp;lt;code&amp;gt;pwr_mgr_init_sequencer(info);&amp;lt;/code&amp;gt;).&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;code&amp;gt;pwr_mgr_init_sequencer&amp;lt;/code&amp;gt;: &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;* writes the I2C commands from &amp;lt;code&amp;gt;info-&amp;amp;gt;i2c_cmds&amp;lt;/code&amp;gt; using &amp;lt;code&amp;gt;pwr_mgr_pm_i2c_cmd_write&amp;lt;/code&amp;gt; * writes the data from &amp;lt;code&amp;gt;info-&amp;amp;gt;i2c_var_data&amp;lt;/code&amp;gt; using &amp;lt;code&amp;gt;pwr_mgr_pm_i2c_var_data_write&amp;lt;/code&amp;gt; * writes command pointers for each volt ??? from &amp;lt;code&amp;gt;info-&amp;amp;gt;i2c_cmd_ptr&amp;lt;/code&amp;gt; using &amp;lt;code&amp;gt;pwr_mgr_set_v0x_specific_i2c_cmd_ptr&amp;lt;/code&amp;gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;code&amp;gt;pwr_mgr_init_sequencer&amp;lt;/code&amp;gt;:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Back to &amp;lt;code&amp;gt;pwr_mgr_init&amp;lt;/code&amp;gt;, it sets &amp;lt;code&amp;gt;pwr_mgr.i2c_seq_trg = 0&amp;lt;/code&amp;gt; and calls the following: * &amp;lt;code&amp;gt;init_completion(&amp;amp;amp;pwr_mgr.i2c_seq_done);&amp;lt;/code&amp;gt; - this sets up a [https://embetronicx.com/tutorials/linux/device-drivers/completion-in-linux/ completion handler] (&amp;lt;code&amp;gt;include/linux/completion.h&amp;lt;/code&amp;gt;) * &amp;lt;code&amp;gt;INIT_WORK(&amp;amp;amp;pwr_mgr.pwrmgr_work, pwr_mgr_work_handler);&amp;lt;/code&amp;gt; - this sets up a [https://www.oreilly.com/library/view/understanding-the-linux/0596005652/ch04s08.html work queue] (&amp;lt;code&amp;gt;kernel/workqueue.c&amp;lt;/code&amp;gt;).&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;* writes the I2C commands from &amp;lt;code&amp;gt;info-&amp;amp;gt;i2c_cmds&amp;lt;/code&amp;gt; using &amp;lt;code&amp;gt;pwr_mgr_pm_i2c_cmd_write&amp;lt;/code&amp;gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;* writes the data from &amp;lt;code&amp;gt;info-&amp;amp;gt;i2c_var_data&amp;lt;/code&amp;gt; using &amp;lt;code&amp;gt;pwr_mgr_pm_i2c_var_data_write&amp;lt;/code&amp;gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;* writes command pointers for each volt ??? from &amp;lt;code&amp;gt;info-&amp;amp;gt;i2c_cmd_ptr&amp;lt;/code&amp;gt; using &amp;lt;code&amp;gt;pwr_mgr_set_v0x_specific_i2c_cmd_ptr&amp;lt;/code&amp;gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt; &lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Back to &amp;lt;code&amp;gt;pwr_mgr_init&amp;lt;/code&amp;gt;, it sets &amp;lt;code&amp;gt;pwr_mgr.i2c_seq_trg = 0&amp;lt;/code&amp;gt; and calls the following:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt; &lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &amp;lt;code&amp;gt;init_completion(&amp;amp;amp;pwr_mgr.i2c_seq_done);&amp;lt;/code&amp;gt; - this sets up a [https://embetronicx.com/tutorials/linux/device-drivers/completion-in-linux/ completion handler] (&amp;lt;code&amp;gt;include/linux/completion.h&amp;lt;/code&amp;gt;)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &amp;lt;code&amp;gt;INIT_WORK(&amp;amp;amp;pwr_mgr.pwrmgr_work, pwr_mgr_work_handler);&amp;lt;/code&amp;gt; - this sets up a [https://www.oreilly.com/library/view/understanding-the-linux/0596005652/ch04s08.html work queue] (&amp;lt;code&amp;gt;kernel/workqueue.c&amp;lt;/code&amp;gt;).&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Then, it runs &amp;lt;code&amp;gt;pwr_mgr_mask_intr(PWRMGR_INTR_ALL, true);&amp;lt;/code&amp;gt; to mask all interrupts by default.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Then, it runs &amp;lt;code&amp;gt;pwr_mgr_mask_intr(PWRMGR_INTR_ALL, true);&amp;lt;/code&amp;gt; to mask all interrupts by default.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l130&quot;&gt;Line 130:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 137:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;span id=&amp;quot;events&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;span id=&amp;quot;events&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Events ==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Events ==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key my_wiki-mediawiki-:diff:1.41:old-26:rev-27:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>Knuxify</name></author>
	</entry>
	<entry>
		<id>https://wiki.dissonant.dev/index.php?title=Mainline:Broadcom_Kona/Power_Manager&amp;diff=26&amp;oldid=prev</id>
		<title>Knuxify: /* Sequencer */</title>
		<link rel="alternate" type="text/html" href="https://wiki.dissonant.dev/index.php?title=Mainline:Broadcom_Kona/Power_Manager&amp;diff=26&amp;oldid=prev"/>
		<updated>2025-01-20T17:19:45Z</updated>

		<summary type="html">&lt;p&gt;&lt;span class=&quot;autocomment&quot;&gt;Sequencer&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 19:19, 20 January 2025&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l141&quot;&gt;Line 141:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 141:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;There is code for both a HW sequencer and a SW sequencer. As evidenced by the comments, they cannot both run at once or timeouts will happen.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;There is code for both a HW sequencer and a SW sequencer. As evidenced by the comments, they cannot both run at once or timeouts will happen.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Downstream driver defines multiple erratas for these. In our case: * CONFIG_KONA_PWRMGR_SWSEQ_FAKE_TRG_ERRATUM=y * CONFIG_KONA_PWRMGR_SWSEQ_RETRY_WORKAROUND=y&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Downstream driver defines multiple erratas for these. In our case:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt; &lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&amp;lt;code&amp;gt;&lt;/ins&gt;CONFIG_KONA_PWRMGR_SWSEQ_FAKE_TRG_ERRATUM=y&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&amp;lt;/code&amp;gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&amp;lt;code&amp;gt;&lt;/ins&gt;CONFIG_KONA_PWRMGR_SWSEQ_RETRY_WORKAROUND=y&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&amp;lt;/code&amp;gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;This sequencer can control voltage requests and PC pin status.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;This sequencer can control voltage requests and PC pin status.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l233&quot;&gt;Line 233:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 236:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;span id=&amp;quot;power-island&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;span id=&amp;quot;power-island&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Power Island ==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Power Island ==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key my_wiki-mediawiki-:diff:1.41:old-25:rev-26:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>Knuxify</name></author>
	</entry>
	<entry>
		<id>https://wiki.dissonant.dev/index.php?title=Mainline:Broadcom_Kona/Power_Manager&amp;diff=25&amp;oldid=prev</id>
		<title>Knuxify: Created page with &quot;* Base address: &lt;code&gt;0x35010000&lt;/code&gt;  &lt;span id=&quot;revisions&quot;&gt;&lt;/span&gt; == Revisions ==  There exist two revisions of the Power Manager: REV0 (capri) and REV2 (hawaii, java). Here is a list of known differences:  * A second set of voltage controllers is introduced in REV02. ** To go with the second VO, a second sequencer command bank is introduced. * A new i2c command, &lt;code&gt;PWRMGR_I2C_APB_READ_OFFSET&lt;/code&gt;, is introduced in REV02. This register contains i2c data and i2c...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.dissonant.dev/index.php?title=Mainline:Broadcom_Kona/Power_Manager&amp;diff=25&amp;oldid=prev"/>
		<updated>2025-01-20T17:18:55Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;* Base address: &amp;lt;code&amp;gt;0x35010000&amp;lt;/code&amp;gt;  &amp;lt;span id=&amp;quot;revisions&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; == Revisions ==  There exist two revisions of the Power Manager: REV0 (capri) and REV2 (hawaii, java). Here is a list of known differences:  * A second set of voltage controllers is introduced in REV02. ** To go with the second VO, a second sequencer command bank is introduced. * A new i2c command, &amp;lt;code&amp;gt;PWRMGR_I2C_APB_READ_OFFSET&amp;lt;/code&amp;gt;, is introduced in REV02. This register contains i2c data and i2c...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;* Base address: &amp;lt;code&amp;gt;0x35010000&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;revisions&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Revisions ==&lt;br /&gt;
&lt;br /&gt;
There exist two revisions of the Power Manager: REV0 (capri) and REV2 (hawaii, java). Here is a list of known differences:&lt;br /&gt;
&lt;br /&gt;
* A second set of voltage controllers is introduced in REV02.&lt;br /&gt;
** To go with the second VO, a second sequencer command bank is introduced.&lt;br /&gt;
* A new i2c command, &amp;lt;code&amp;gt;PWRMGR_I2C_APB_READ_OFFSET&amp;lt;/code&amp;gt;, is introduced in REV02. This register contains i2c data and i2c isr register… whatever those are.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;components&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
* Some kind of interrupt controller?&lt;br /&gt;
* Power Island (mostly in separate pi_mgr driver)&lt;br /&gt;
* Sequencer (might be related to those sequences mentioned in PI driver)&lt;br /&gt;
* Some kind of PMU, or connection to the PMU&lt;br /&gt;
* Some kind of voltage controller?&lt;br /&gt;
* Event handler&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;initialization&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Initialization ==&lt;br /&gt;
&lt;br /&gt;
The initialization is first called during early init, through a platform-specific function called &amp;lt;code&amp;gt;hawaii_pwr_mgr_init&amp;lt;/code&amp;gt;, located in the mach- folders.&lt;br /&gt;
&lt;br /&gt;
First, this function initializes some initialization parameters for the pwrmgr from &amp;lt;code&amp;gt;pm_params.c&amp;lt;/code&amp;gt; through &amp;lt;code&amp;gt;pm_params_init&amp;lt;/code&amp;gt;. These are stored in the &amp;lt;code&amp;gt;pwrmgr_init_param&amp;lt;/code&amp;gt; struct in the aforementioned file.&lt;br /&gt;
&lt;br /&gt;
Then, it uses a set of dummy pointers defined in &amp;lt;code&amp;gt;pwr_mgr&amp;lt;/code&amp;gt; to initialize the power manager with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;/**&lt;br /&gt;
 * Load the dummy sequencer during power manager initialization&lt;br /&gt;
 * Actual sequencer will be loaded during pmu i2c driver&lt;br /&gt;
 * initialisation&lt;br /&gt;
 */&amp;lt;/pre&amp;gt;&lt;br /&gt;
At this point, &amp;lt;code&amp;gt;pwr_mgr_init&amp;lt;/code&amp;gt; is called. This function is defined in &amp;lt;code&amp;gt;plat-kona/pwr_mgr.c&amp;lt;/code&amp;gt;, and marks the first time we enter the full platform driver.&lt;br /&gt;
&lt;br /&gt;
The passed dummy struct we created earlier is a &amp;lt;code&amp;gt;pwr_mgr_info&amp;lt;/code&amp;gt; struct. &amp;lt;code&amp;gt;pwr_mgr.info&amp;lt;/code&amp;gt; is set to this value. This indicates to all further functions that the power manager has been initialized. &amp;lt;code&amp;gt;pwr_mgr.sem_locked&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Next, the sequencer is disabled (&amp;lt;code&amp;gt;pwr_mgr_pm_i2c_enable(false)&amp;lt;/code&amp;gt; - [[#I2C_ENABLE_OFFSET - 0x4100]]) and initialized with the provided data (&amp;lt;code&amp;gt;pwr_mgr_init_sequencer(info);&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;pwr_mgr_init_sequencer&amp;lt;/code&amp;gt;: * writes the I2C commands from &amp;lt;code&amp;gt;info-&amp;amp;gt;i2c_cmds&amp;lt;/code&amp;gt; using &amp;lt;code&amp;gt;pwr_mgr_pm_i2c_cmd_write&amp;lt;/code&amp;gt; * writes the data from &amp;lt;code&amp;gt;info-&amp;amp;gt;i2c_var_data&amp;lt;/code&amp;gt; using &amp;lt;code&amp;gt;pwr_mgr_pm_i2c_var_data_write&amp;lt;/code&amp;gt; * writes command pointers for each volt ??? from &amp;lt;code&amp;gt;info-&amp;amp;gt;i2c_cmd_ptr&amp;lt;/code&amp;gt; using &amp;lt;code&amp;gt;pwr_mgr_set_v0x_specific_i2c_cmd_ptr&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Back to &amp;lt;code&amp;gt;pwr_mgr_init&amp;lt;/code&amp;gt;, it sets &amp;lt;code&amp;gt;pwr_mgr.i2c_seq_trg = 0&amp;lt;/code&amp;gt; and calls the following: * &amp;lt;code&amp;gt;init_completion(&amp;amp;amp;pwr_mgr.i2c_seq_done);&amp;lt;/code&amp;gt; - this sets up a [https://embetronicx.com/tutorials/linux/device-drivers/completion-in-linux/ completion handler] (&amp;lt;code&amp;gt;include/linux/completion.h&amp;lt;/code&amp;gt;) * &amp;lt;code&amp;gt;INIT_WORK(&amp;amp;amp;pwr_mgr.pwrmgr_work, pwr_mgr_work_handler);&amp;lt;/code&amp;gt; - this sets up a [https://www.oreilly.com/library/view/understanding-the-linux/0596005652/ch04s08.html work queue] (&amp;lt;code&amp;gt;kernel/workqueue.c&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Then, it runs &amp;lt;code&amp;gt;pwr_mgr_mask_intr(PWRMGR_INTR_ALL, true);&amp;lt;/code&amp;gt; to mask all interrupts by default.&lt;br /&gt;
&lt;br /&gt;
Lastly, it requests an IRQ using &amp;lt;code&amp;gt;request_irq&amp;lt;/code&amp;gt;, using &amp;lt;code&amp;gt;info-&amp;amp;gt;pwrmgr_intr&amp;lt;/code&amp;gt; as the interrupt number, with the handler set to &amp;lt;code&amp;gt;pwr_mgr_irq_handler&amp;lt;/code&amp;gt; ([https://embetronicx.com/tutorials/linux/device-drivers/linux-device-driver-tutorial-part-13-interrupt-example-program-in-linux-kernel/ ref]).&lt;br /&gt;
&lt;br /&gt;
This is the end of the &amp;lt;code&amp;gt;pwr_mgr_init&amp;lt;/code&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
We return to the &amp;lt;code&amp;gt;mach-{}/pwr_mgr.c&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
The next things that happen:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;hawaii_pi_mgr_init&amp;lt;/code&amp;gt; is called. This is described in the PI section.&lt;br /&gt;
* Some erratum stuff happens. Check later.&lt;br /&gt;
* A wakeup override is set for the MM (multimedia) CCU (core clock, handles stuff like camera, DSI, GPU) using &amp;lt;code&amp;gt;pwr_mgr_pi_set_wakeup_override(PI_MGR_PI_ID_MM, false /*clear */);&amp;lt;/code&amp;gt;. This might be related to the workarounds in &amp;lt;code&amp;gt;pwr_mgr_init_sequencer&amp;lt;/code&amp;gt;?&lt;br /&gt;
* &amp;lt;code&amp;gt;pwr_mgr_event_clear_events&amp;lt;/code&amp;gt; is called on all events.&lt;br /&gt;
* &amp;lt;code&amp;gt;pwr_mgr_event_set&amp;lt;/code&amp;gt; sets &amp;lt;code&amp;gt;SOFTWARE_2_EVENT&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SOFTWARE_0_EVENT&amp;lt;/code&amp;gt; to 1.&lt;br /&gt;
&lt;br /&gt;
Then some pin control stuff happens:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;    pwr_mgr_set_pc_sw_override(PC0, false, 0);&lt;br /&gt;
    pwr_mgr_set_pc_clkreq_override(PC0, true, 1);&lt;br /&gt;
&lt;br /&gt;
    /* make sure that PC1, PC2 software override&lt;br /&gt;
     * is cleared so that sequencer can toggle these&lt;br /&gt;
     * pins during retention/off/wakeup&lt;br /&gt;
     */&lt;br /&gt;
    pwr_mgr_set_pc_sw_override(PC1, false, 0);&lt;br /&gt;
    pwr_mgr_set_pc_sw_override(PC2, false, 0);&lt;br /&gt;
    pwr_mgr_set_pc_sw_override(PC3, false, 0);&lt;br /&gt;
    pwr_mgr_set_pc_clkreq_override(PC1, false, 0);&lt;br /&gt;
    pwr_mgr_set_pc_clkreq_override(PC2, false, 0);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Then we call &amp;lt;code&amp;gt;pwr_mgr_pm_i2c_enable(true);&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Then, the event table is initialized:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;    /*Init event table */&lt;br /&gt;
    for (i = 0; i &amp;lt; ARRAY_SIZE(__event_table); i++) {&lt;br /&gt;
        pwr_mgr_event_trg_enable(__event_table[i].event_id,&lt;br /&gt;
                     __event_table[i].trig_type);&lt;br /&gt;
&lt;br /&gt;
        cfg.policy = __event_table[i].policy_modem;&lt;br /&gt;
        pwr_mgr_event_set_pi_policy(__event_table[i].event_id,&lt;br /&gt;
                        PI_MGR_PI_ID_MODEM, &amp;amp;cfg);&lt;br /&gt;
&lt;br /&gt;
        cfg.policy = __event_table[i].policy_arm;&lt;br /&gt;
        pwr_mgr_event_set_pi_policy(__event_table[i].event_id,&lt;br /&gt;
                        PI_MGR_PI_ID_ARM_CORE, &amp;amp;cfg);&lt;br /&gt;
&lt;br /&gt;
        cfg.policy = __event_table[i].policy_arm_sub;&lt;br /&gt;
        pwr_mgr_event_set_pi_policy(__event_table[i].event_id,&lt;br /&gt;
                        PI_MGR_PI_ID_ARM_SUB_SYSTEM, &amp;amp;cfg);&lt;br /&gt;
&lt;br /&gt;
        cfg.policy = __event_table[i].policy_aon;&lt;br /&gt;
        pwr_mgr_event_set_pi_policy(__event_table[i].event_id,&lt;br /&gt;
                        PI_MGR_PI_ID_HUB_AON, &amp;amp;cfg);&lt;br /&gt;
&lt;br /&gt;
        cfg.policy = __event_table[i].policy_hub;&lt;br /&gt;
        pwr_mgr_event_set_pi_policy(__event_table[i].event_id,&lt;br /&gt;
                        PI_MGR_PI_ID_HUB_SWITCHABLE, &amp;amp;cfg);&lt;br /&gt;
&lt;br /&gt;
        cfg.policy = __event_table[i].policy_mm;&lt;br /&gt;
        pwr_mgr_event_set_pi_policy(__event_table[i].event_id,&lt;br /&gt;
                        PI_MGR_PI_ID_MM, &amp;amp;cfg);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The following sets up some kind of event triggers… not that they seem to do much that the others don’t. Only happens on java. Might be related to the 4 CPU cores as opposed to hawaii’s 2?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;    /*Map core timer interrupts to COMMON_TIMER_3_EVENT and&lt;br /&gt;
    *COMMON_TIMER_4_EVENT events.&lt;br /&gt;
    *Set timer_wu_event_sel to 0x3 to map both slave and core timer&lt;br /&gt;
    *interrupts to these events*/&lt;br /&gt;
    reg_val = readl(KONA_CHIPREG_VA + CHIPREG_PERIPH_SPARE_CONTROL1_OFFSET);&lt;br /&gt;
    reg_val |= 0x3 &amp;lt;&amp;lt;&lt;br /&gt;
        CHIPREG_PERIPH_SPARE_CONTROL1_TIMER_WU_EVENT_SEL_SHIFT;&lt;br /&gt;
    writel(reg_val,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Then we init all PIs using &amp;lt;code&amp;gt;pi_init&amp;lt;/code&amp;gt; on the PI recieved with &amp;lt;code&amp;gt;pi_mgr_get&amp;lt;/code&amp;gt; on every ID.&lt;br /&gt;
&lt;br /&gt;
Finally, we call &amp;lt;code&amp;gt;__clock_init()&amp;lt;/code&amp;gt;. Then clock setup happens for CPU speed (only used on Hawaii chips with lower clocks.)&lt;br /&gt;
&lt;br /&gt;
This is the end of the &amp;lt;code&amp;gt;hawaii_pwr_mgr_init&amp;lt;/code&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
There are two more late init functions:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;hawaii_pwr_mgr_late_init&amp;lt;/code&amp;gt; which runs &amp;lt;code&amp;gt;hawaii_pwr_mgr_delayed_init&amp;lt;/code&amp;gt;, which in turn runs &amp;lt;code&amp;gt;pi_init_state&amp;lt;/code&amp;gt; on every PI;&lt;br /&gt;
* &amp;lt;code&amp;gt;mach_init_sequencer&amp;lt;/code&amp;gt; which initializes the sequencer with real values and “on return PWRMGR I2C block will be enabled”.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;events&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Events ==&lt;br /&gt;
&lt;br /&gt;
Events are called on specific actions in the system. When they occur, they set the PI policies. There are multiple types of trigger mechanisms for events.&lt;br /&gt;
&lt;br /&gt;
A full list of events is present at &amp;lt;code&amp;gt;arch/arm/mach-java/include/mach/pwr_mgr.h&amp;lt;/code&amp;gt;. Not all of them trigger policy changes; the ones that do are defined in &amp;lt;code&amp;gt;arch/arm/mach-java/pwr_mgr.c&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;sequencer&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Sequencer ==&lt;br /&gt;
&lt;br /&gt;
There is code for both a HW sequencer and a SW sequencer. As evidenced by the comments, they cannot both run at once or timeouts will happen.&lt;br /&gt;
&lt;br /&gt;
Downstream driver defines multiple erratas for these. In our case: * CONFIG_KONA_PWRMGR_SWSEQ_FAKE_TRG_ERRATUM=y * CONFIG_KONA_PWRMGR_SWSEQ_RETRY_WORKAROUND=y&lt;br /&gt;
&lt;br /&gt;
This sequencer can control voltage requests and PC pin status.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;sequencer-commands&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Sequencer commands ===&lt;br /&gt;
&lt;br /&gt;
The sequencer has 2 command banks, each of which stores 64 commands. Each command consists of a 4-bit command number and an 8-bit value.&lt;br /&gt;
&lt;br /&gt;
REV02 has 2 command banks, REV00 only has one.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Address&lt;br /&gt;
! Name&lt;br /&gt;
! Description (as found in downstream kernel)&lt;br /&gt;
! Used?&lt;br /&gt;
|-&lt;br /&gt;
| 0x0&lt;br /&gt;
| REG_ADDR&lt;br /&gt;
| sets the next address for read/write data&lt;br /&gt;
| Y&lt;br /&gt;
|-&lt;br /&gt;
| 0x1&lt;br /&gt;
| REG_DATA&lt;br /&gt;
| executes a write to I2C controller via APB&lt;br /&gt;
| F&lt;br /&gt;
|-&lt;br /&gt;
| 0x2&lt;br /&gt;
| I2C_DATA&lt;br /&gt;
| data to be written to PMU via I2C&lt;br /&gt;
| F&lt;br /&gt;
|-&lt;br /&gt;
| 0x3&lt;br /&gt;
| I2C_VAR&lt;br /&gt;
| data returned for voltage lookup (payload is the index to table)&lt;br /&gt;
| F&lt;br /&gt;
|-&lt;br /&gt;
| 0x4&lt;br /&gt;
| WAIT_I2C_RETX&lt;br /&gt;
| wait for retry from I2C control register&lt;br /&gt;
| N&lt;br /&gt;
|-&lt;br /&gt;
| 0x5&lt;br /&gt;
| WAIT_I2C_STAT&lt;br /&gt;
| wait for good status (loop until good)&lt;br /&gt;
| N&lt;br /&gt;
|-&lt;br /&gt;
| 0x6&lt;br /&gt;
| WAIT_TIMER&lt;br /&gt;
| wait for the number of clocks in the payload&lt;br /&gt;
| Y&lt;br /&gt;
|-&lt;br /&gt;
| 0x7&lt;br /&gt;
| END&lt;br /&gt;
| stop and wait for new voltage request change&lt;br /&gt;
| Y&lt;br /&gt;
|-&lt;br /&gt;
| 0x8&lt;br /&gt;
| SET_PC_PINS&lt;br /&gt;
| pc pins are set based on value and mask&lt;br /&gt;
| Y&lt;br /&gt;
|-&lt;br /&gt;
| 0x9&lt;br /&gt;
| SET_UPPER_DATA&lt;br /&gt;
| sets the data in the upper byte of apb data bus&lt;br /&gt;
| N&lt;br /&gt;
|-&lt;br /&gt;
| 0xA&lt;br /&gt;
| READ_FIFO&lt;br /&gt;
| read i2c fifo&lt;br /&gt;
| F&lt;br /&gt;
|-&lt;br /&gt;
| 0xB&lt;br /&gt;
| SET_READ_DATA&lt;br /&gt;
| copy I2C read data to PWRMGR register&lt;br /&gt;
| F&lt;br /&gt;
|-&lt;br /&gt;
| 0xE&lt;br /&gt;
| JUMP_VOLTAGE&lt;br /&gt;
| jump to address based on current voltage request&lt;br /&gt;
| Y&lt;br /&gt;
|-&lt;br /&gt;
| 0xF&lt;br /&gt;
| JUMP&lt;br /&gt;
| jump to address defined in payload&lt;br /&gt;
| F&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
(Y - yes in dummy, F - yes in full table, N - not at all)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;power-island&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Power Island ==&lt;br /&gt;
&lt;br /&gt;
The Power Islands are power domains managed by the Power Manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;what-makes-a-power-island&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== What makes a Power Island ===&lt;br /&gt;
&lt;br /&gt;
There are 6 [[#Power Islands]] as defined in the code. Each power island has a &amp;#039;&amp;#039;&amp;#039;policy&amp;#039;&amp;#039;&amp;#039;, and has a controllable frequency and wake-up latency.&lt;br /&gt;
&lt;br /&gt;
Power islands are pretty closely tied to the CCU. Both the DFS and QoS requests are sent to the CCU, and managed the frequency policy and voltage policy respectively.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;dfs-and-qos&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== DFS and QoS ===&lt;br /&gt;
&lt;br /&gt;
ref: Documentation/Broadcom/Kona_PM_DFS_and_QOS_API.txt in downstream kernel&lt;br /&gt;
&lt;br /&gt;
DFS APIs are used to control the &amp;#039;&amp;#039;&amp;#039;frequency&amp;#039;&amp;#039;&amp;#039;, or to be exact, &amp;#039;&amp;#039;&amp;#039;OPP mode&amp;#039;&amp;#039;&amp;#039; (see [[#OPP types]]), of a specific PI. QoS APIs are used to control the &amp;#039;&amp;#039;&amp;#039;maximum wake-up latency&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
Both of these APIs work through a system of “requests”; clients can make requests by using &amp;lt;code&amp;gt;add_request&amp;lt;/code&amp;gt; (this creates a “node” which is usually stored somewhere in the client’s driver), change their value using &amp;lt;code&amp;gt;request_update&amp;lt;/code&amp;gt; or remove the request by using &amp;lt;code&amp;gt;request_remove&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;initialization-1&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Initialization ===&lt;br /&gt;
&lt;br /&gt;
Initialization begins in &amp;lt;code&amp;gt;mach-{}/pi_mgr.c&amp;lt;/code&amp;gt;., where &amp;lt;code&amp;gt;hawaii_pi_mgr_init&amp;lt;/code&amp;gt; is called. This does some errata stuff, runs &amp;lt;code&amp;gt;pi_mgr_init&amp;lt;/code&amp;gt; and finally calls &amp;lt;code&amp;gt;pi_mgr_register&amp;lt;/code&amp;gt; on every PI. This file defines the default settings for each PI.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;pi_mgr_init&amp;lt;/code&amp;gt; is defined in &amp;lt;code&amp;gt;arch/arm/plat-kona/pi_mgr.c&amp;lt;/code&amp;gt;. It does two things: * Initializes memory for the pi_mgr data: &amp;lt;code&amp;gt;memset(&amp;amp;amp;pi_mgr, 0, sizeof(pi_mgr));&amp;lt;/code&amp;gt; * Sets &amp;lt;code&amp;gt;pi_mgr.init = 1;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Most of the actual PI initialization is actually done in the power manager initialization sequence.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;policies&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Policies ===&lt;br /&gt;
&lt;br /&gt;
From &amp;lt;code&amp;gt;arch/arm/mach-java/include/mach/pwr_mgr.h&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#define PM_OFF      0  /* Shutdown policy */&lt;br /&gt;
#define PM_RET      1  /* Retention policy */&lt;br /&gt;
#define PM_ECO      4  /* Economy */&lt;br /&gt;
#define PM_DFS      5  /* also RUN_POLICY; see [[#DFS and QoS]] */&lt;br /&gt;
#define PM_WKP      7  /* wakeup? */&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;pwr_mgr_pi_set_wakeup_override&amp;lt;/code&amp;gt; needs to be called before policies can be changed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;raw-data&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Raw data ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;nodes&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
==== Nodes ====&lt;br /&gt;
&lt;br /&gt;
* DFS (Dynamic Frequency Scaling?) and QOS (Quality of Service?)&lt;br /&gt;
* Both have some kind of requests (add_request, update_request in plat-kona/pi_mgr.c)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;opp-types&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
==== OPP types ====&lt;br /&gt;
&lt;br /&gt;
\:src: arch/arm/mach-java/include/mach/pi_mgr.h&lt;br /&gt;
&lt;br /&gt;
OPP stands for “operating frequency”. See [[#DFS and QoS]].&lt;br /&gt;
&lt;br /&gt;
* 0 - XTAL&lt;br /&gt;
* 1 - ECONOMY&lt;br /&gt;
* 2 - NORMAL&lt;br /&gt;
* 3 - TURBO&lt;br /&gt;
* 4 - SUPER_TURBO&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;power-islands&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
==== Power Islands ====&lt;br /&gt;
&lt;br /&gt;
\:src: arch/arm/mach-java/include/mach/pi_mgr.h&lt;br /&gt;
&lt;br /&gt;
* MM&lt;br /&gt;
* HUB_SWITCHABLE&lt;br /&gt;
* HUB_AON&lt;br /&gt;
* ARM_CORE&lt;br /&gt;
* ARM_SUB_SYSTEM&lt;br /&gt;
* MODEM&lt;br /&gt;
&lt;br /&gt;
Each has 3 states: ACTIVE, RETENTION, and SHUTDOWN; ARM cores have ACTIVE, SUSPEND, RETENTION and DORMANT.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;raw-data-1&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Raw data ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;i2c-value-offsets&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== I2C value offsets ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;intr_status---0x40a0&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
==== INTR_STATUS - 0x40A0 ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;intr_mask---0x40a4&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
==== INTR_MASK - 0x40A4 ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;event_bank1_offset---0x40a8&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
==== EVENT_BANK1_OFFSET - 0x40A8 ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;i2c_enable_offset---0x4100&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
==== I2C_ENABLE_OFFSET - 0x4100 ====&lt;br /&gt;
&lt;br /&gt;
Writing 0x0000001 enables the sequencer, 0x00000000 disables it. See &amp;lt;code&amp;gt;pwr_mgr_pm_i2c_enable&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;i2c_cmd_bank0_offset---0x4104&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
==== I2C_CMD_BANK0_OFFSET - 0x4104 ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;i2c_cmd_bank1_offset---0x4280&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
==== I2C_CMD_BANK1_OFFSET - 0x4280 ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;i2c_sw_cmd_ctrl---0x41b8&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
==== I2C_SW_CMD_CTRL - 0x41B8 ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;PWRMGR_I2C_REQ_TRG_MASK&amp;lt;/code&amp;gt; - enables/disables software sequencer&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;i2c_apb_read&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
==== I2C_APB_READ ====&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;REV02 only&amp;#039;&amp;#039;&amp;#039;. 0x41CC, mask 0xFF, shift 0.&lt;/div&gt;</summary>
		<author><name>Knuxify</name></author>
	</entry>
</feed>