# SPDX-License-Identifier: GPL-2.0-only # # Copyright (C) 2017 Yousong Zhou <yszhou4tech@gmail.com> include $(TOPDIR)/rules.mk BOARD:=armvirt BOARDNAME:=QEMU ARM Virtual Machine FEATURES:=fpu pci rtc usb FEATURES+=cpiogz ext4 ramdisk squashfs targz KERNEL_PATCHVER:=5.10 KERNEL_TESTING_PATCHVER:=5.15 include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES += mkf2fs e2fsprogs $(eval $(call BuildTarget)) -otto-watchdog-timer.patch?h=master' type='application/atom+xml'/> <link rel='vcs-git' href='git://git.panaceas.org/openwrt/upstream' title='openwrt/upstream Git repository'/> <link rel='vcs-git' href='ssh://git@git.panaceas.org/git/openwrt/upstream' title='openwrt/upstream Git repository'/> </head> <body> <div id='cgit'><table id='header'> <tr> <td class='logo' rowspan='2'><a href='/cgit/'><img src='/cgit.png' alt='cgit logo'/></a></td> <td class='main'><a href='/cgit/'>index</a> : <a title='openwrt/upstream' href='/cgit/openwrt/upstream/'>openwrt/upstream</a></td><td class='form'><form method='get'> <input type='hidden' name='id' value='736257141f7e2b4cc13c3fe297ecca0b21bcea4b'/><select name='h' onchange='this.form.submit();'> <option value='attitude_adjustment'>attitude_adjustment</option> <option value='barrier_breaker'>barrier_breaker</option> <option value='chaos_calmer'>chaos_calmer</option> <option value='lede-17.01'>lede-17.01</option> <option value='less-old-master'>less-old-master</option> <option value='master' selected='selected'>master</option> <option value='old-master'>old-master</option> <option value='openwrt-18.06'>openwrt-18.06</option> <option value='openwrt-19.07'>openwrt-19.07</option> <option value='upstream'>upstream</option> </select> <input type='submit' value='switch'/></form></td></tr> <tr><td class='sub'>upstream openwrt</td><td class='sub right'>James</td></tr></table> <table class='tabs'><tr><td> <a href='/cgit/openwrt/upstream/about/'>about</a><a href='/cgit/openwrt/upstream/'>summary</a><a href='/cgit/openwrt/upstream/refs/?id=736257141f7e2b4cc13c3fe297ecca0b21bcea4b'>refs</a><a href='/cgit/openwrt/upstream/log/target/linux/realtek/patches-5.15/008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch'>log</a><a class='active' href='/cgit/openwrt/upstream/tree/target/linux/realtek/patches-5.15/008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch?id=736257141f7e2b4cc13c3fe297ecca0b21bcea4b'>tree</a><a href='/cgit/openwrt/upstream/commit/target/linux/realtek/patches-5.15/008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch?id=736257141f7e2b4cc13c3fe297ecca0b21bcea4b'>commit</a><a href='/cgit/openwrt/upstream/diff/target/linux/realtek/patches-5.15/008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch?id=736257141f7e2b4cc13c3fe297ecca0b21bcea4b'>diff</a><a href='/cgit/openwrt/upstream/stats/target/linux/realtek/patches-5.15/008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch'>stats</a></td><td class='form'><form class='right' method='get' action='/cgit/openwrt/upstream/log/target/linux/realtek/patches-5.15/008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch'> <input type='hidden' name='id' value='736257141f7e2b4cc13c3fe297ecca0b21bcea4b'/><select name='qt'> <option value='grep'>log msg</option> <option value='author'>author</option> <option value='committer'>committer</option> <option value='range'>range</option> </select> <input class='txt' type='search' size='10' name='q' value=''/> <input type='submit' value='search'/> </form> </td></tr></table> <div class='path'>path: <a href='/cgit/openwrt/upstream/tree/?id=736257141f7e2b4cc13c3fe297ecca0b21bcea4b'>root</a>/<a href='/cgit/openwrt/upstream/tree/target?id=736257141f7e2b4cc13c3fe297ecca0b21bcea4b'>target</a>/<a href='/cgit/openwrt/upstream/tree/target/linux?id=736257141f7e2b4cc13c3fe297ecca0b21bcea4b'>linux</a>/<a href='/cgit/openwrt/upstream/tree/target/linux/realtek?id=736257141f7e2b4cc13c3fe297ecca0b21bcea4b'>realtek</a>/<a href='/cgit/openwrt/upstream/tree/target/linux/realtek/patches-5.15?id=736257141f7e2b4cc13c3fe297ecca0b21bcea4b'>patches-5.15</a>/<a href='/cgit/openwrt/upstream/tree/target/linux/realtek/patches-5.15/008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch?id=736257141f7e2b4cc13c3fe297ecca0b21bcea4b'>008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch</a></div><div class='content'>blob: 93f0fe5cf475dc9ec2f2f679d22548c94a558416 (<a href='/cgit/openwrt/upstream/plain/target/linux/realtek/patches-5.15/008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch?id=736257141f7e2b4cc13c3fe297ecca0b21bcea4b'>plain</a>) <table summary='blob content' class='blob'> <tr><td class='linenumbers'><pre><a id='n1' href='#n1'>1</a> <a id='n2' href='#n2'>2</a> <a id='n3' href='#n3'>3</a> <a id='n4' href='#n4'>4</a> <a id='n5' href='#n5'>5</a> <a id='n6' href='#n6'>6</a> <a id='n7' href='#n7'>7</a> <a id='n8' href='#n8'>8</a> <a id='n9' href='#n9'>9</a> <a id='n10' href='#n10'>10</a> <a id='n11' href='#n11'>11</a> <a id='n12' href='#n12'>12</a> <a id='n13' href='#n13'>13</a> <a id='n14' href='#n14'>14</a> <a id='n15' href='#n15'>15</a> <a id='n16' href='#n16'>16</a> <a id='n17' href='#n17'>17</a> <a id='n18' href='#n18'>18</a> <a id='n19' href='#n19'>19</a> <a id='n20' href='#n20'>20</a> <a id='n21' href='#n21'>21</a> <a id='n22' href='#n22'>22</a> <a id='n23' href='#n23'>23</a> <a id='n24' href='#n24'>24</a> <a id='n25' href='#n25'>25</a> <a id='n26' href='#n26'>26</a> <a id='n27' href='#n27'>27</a> <a id='n28' href='#n28'>28</a> <a id='n29' href='#n29'>29</a> <a id='n30' href='#n30'>30</a> <a id='n31' href='#n31'>31</a> <a id='n32' href='#n32'>32</a> <a id='n33' href='#n33'>33</a> <a id='n34' href='#n34'>34</a> <a id='n35' href='#n35'>35</a> <a id='n36' href='#n36'>36</a> <a id='n37' href='#n37'>37</a> <a id='n38' href='#n38'>38</a> <a id='n39' href='#n39'>39</a> <a id='n40' href='#n40'>40</a> <a id='n41' href='#n41'>41</a> <a id='n42' href='#n42'>42</a> <a id='n43' href='#n43'>43</a> <a id='n44' href='#n44'>44</a> <a id='n45' href='#n45'>45</a> <a id='n46' href='#n46'>46</a> <a id='n47' href='#n47'>47</a> <a id='n48' href='#n48'>48</a> <a id='n49' href='#n49'>49</a> <a id='n50' href='#n50'>50</a> <a id='n51' href='#n51'>51</a> <a id='n52' href='#n52'>52</a> <a id='n53' href='#n53'>53</a> <a id='n54' href='#n54'>54</a> <a id='n55' href='#n55'>55</a> <a id='n56' href='#n56'>56</a> <a id='n57' href='#n57'>57</a> <a id='n58' href='#n58'>58</a> <a id='n59' href='#n59'>59</a> <a id='n60' href='#n60'>60</a> <a id='n61' href='#n61'>61</a> <a id='n62' href='#n62'>62</a> <a id='n63' href='#n63'>63</a> <a id='n64' href='#n64'>64</a> <a id='n65' href='#n65'>65</a> <a id='n66' href='#n66'>66</a> <a id='n67' href='#n67'>67</a> <a id='n68' href='#n68'>68</a> <a id='n69' href='#n69'>69</a> <a id='n70' href='#n70'>70</a> <a id='n71' href='#n71'>71</a> <a id='n72' href='#n72'>72</a> <a id='n73' href='#n73'>73</a> <a id='n74' href='#n74'>74</a> <a id='n75' href='#n75'>75</a> <a id='n76' href='#n76'>76</a> <a id='n77' href='#n77'>77</a> <a id='n78' href='#n78'>78</a> <a id='n79' href='#n79'>79</a> <a id='n80' href='#n80'>80</a> <a id='n81' href='#n81'>81</a> <a id='n82' href='#n82'>82</a> <a id='n83' href='#n83'>83</a> <a id='n84' href='#n84'>84</a> <a id='n85' href='#n85'>85</a> <a id='n86' href='#n86'>86</a> <a id='n87' href='#n87'>87</a> <a id='n88' href='#n88'>88</a> <a id='n89' href='#n89'>89</a> <a id='n90' href='#n90'>90</a> <a id='n91' href='#n91'>91</a> <a id='n92' href='#n92'>92</a> <a id='n93' href='#n93'>93</a> <a id='n94' href='#n94'>94</a> <a id='n95' href='#n95'>95</a> <a id='n96' href='#n96'>96</a> <a id='n97' href='#n97'>97</a> <a id='n98' href='#n98'>98</a> <a id='n99' href='#n99'>99</a> <a id='n100' href='#n100'>100</a> <a id='n101' href='#n101'>101</a> <a id='n102' href='#n102'>102</a> <a id='n103' href='#n103'>103</a> <a id='n104' href='#n104'>104</a> <a id='n105' href='#n105'>105</a> <a id='n106' href='#n106'>106</a> <a id='n107' href='#n107'>107</a> <a id='n108' href='#n108'>108</a> <a id='n109' href='#n109'>109</a> <a id='n110' href='#n110'>110</a> <a id='n111' href='#n111'>111</a> <a id='n112' href='#n112'>112</a> <a id='n113' href='#n113'>113</a> <a id='n114' href='#n114'>114</a> <a id='n115' href='#n115'>115</a> <a id='n116' href='#n116'>116</a> <a id='n117' href='#n117'>117</a> <a id='n118' href='#n118'>118</a> <a id='n119' href='#n119'>119</a> <a id='n120' href='#n120'>120</a> <a id='n121' href='#n121'>121</a> <a id='n122' href='#n122'>122</a> <a id='n123' href='#n123'>123</a> <a id='n124' href='#n124'>124</a> <a id='n125' href='#n125'>125</a> <a id='n126' href='#n126'>126</a> <a id='n127' href='#n127'>127</a> <a id='n128' href='#n128'>128</a> <a id='n129' href='#n129'>129</a> <a id='n130' href='#n130'>130</a> <a id='n131' href='#n131'>131</a> <a id='n132' href='#n132'>132</a> <a id='n133' href='#n133'>133</a> <a id='n134' href='#n134'>134</a> <a id='n135' href='#n135'>135</a> <a id='n136' href='#n136'>136</a> <a id='n137' href='#n137'>137</a> <a id='n138' href='#n138'>138</a> <a id='n139' href='#n139'>139</a> <a id='n140' href='#n140'>140</a> <a id='n141' href='#n141'>141</a> <a id='n142' href='#n142'>142</a> <a id='n143' href='#n143'>143</a> <a id='n144' href='#n144'>144</a> <a id='n145' href='#n145'>145</a> <a id='n146' href='#n146'>146</a> <a id='n147' href='#n147'>147</a> <a id='n148' href='#n148'>148</a> <a id='n149' href='#n149'>149</a> <a id='n150' href='#n150'>150</a> <a id='n151' href='#n151'>151</a> <a id='n152' href='#n152'>152</a> <a id='n153' href='#n153'>153</a> <a id='n154' href='#n154'>154</a> <a id='n155' href='#n155'>155</a> <a id='n156' href='#n156'>156</a> <a id='n157' href='#n157'>157</a> <a id='n158' href='#n158'>158</a> <a id='n159' href='#n159'>159</a> <a id='n160' href='#n160'>160</a> <a id='n161' href='#n161'>161</a> <a id='n162' href='#n162'>162</a> <a id='n163' href='#n163'>163</a> <a id='n164' href='#n164'>164</a> <a id='n165' href='#n165'>165</a> <a id='n166' href='#n166'>166</a> <a id='n167' href='#n167'>167</a> <a id='n168' href='#n168'>168</a> <a id='n169' href='#n169'>169</a> <a id='n170' href='#n170'>170</a> <a id='n171' href='#n171'>171</a> <a id='n172' href='#n172'>172</a> <a id='n173' href='#n173'>173</a> <a id='n174' href='#n174'>174</a> <a id='n175' href='#n175'>175</a> <a id='n176' href='#n176'>176</a> <a id='n177' href='#n177'>177</a> <a id='n178' href='#n178'>178</a> <a id='n179' href='#n179'>179</a> <a id='n180' href='#n180'>180</a> <a id='n181' href='#n181'>181</a> <a id='n182' href='#n182'>182</a> <a id='n183' href='#n183'>183</a> <a id='n184' href='#n184'>184</a> <a id='n185' href='#n185'>185</a> <a id='n186' href='#n186'>186</a> <a id='n187' href='#n187'>187</a> <a id='n188' href='#n188'>188</a> <a id='n189' href='#n189'>189</a> <a id='n190' href='#n190'>190</a> <a id='n191' href='#n191'>191</a> <a id='n192' href='#n192'>192</a> <a id='n193' href='#n193'>193</a> <a id='n194' href='#n194'>194</a> <a id='n195' href='#n195'>195</a> <a id='n196' href='#n196'>196</a> <a id='n197' href='#n197'>197</a> <a id='n198' href='#n198'>198</a> <a id='n199' href='#n199'>199</a> <a id='n200' href='#n200'>200</a> <a id='n201' href='#n201'>201</a> <a id='n202' href='#n202'>202</a> <a id='n203' href='#n203'>203</a> <a id='n204' href='#n204'>204</a> <a id='n205' href='#n205'>205</a> <a id='n206' href='#n206'>206</a> <a id='n207' href='#n207'>207</a> <a id='n208' href='#n208'>208</a> <a id='n209' href='#n209'>209</a> <a id='n210' href='#n210'>210</a> <a id='n211' href='#n211'>211</a> <a id='n212' href='#n212'>212</a> <a id='n213' href='#n213'>213</a> <a id='n214' href='#n214'>214</a> <a id='n215' href='#n215'>215</a> <a id='n216' href='#n216'>216</a> <a id='n217' href='#n217'>217</a> <a id='n218' href='#n218'>218</a> <a id='n219' href='#n219'>219</a> <a id='n220' href='#n220'>220</a> <a id='n221' href='#n221'>221</a> <a id='n222' href='#n222'>222</a> <a id='n223' href='#n223'>223</a> <a id='n224' href='#n224'>224</a> <a id='n225' href='#n225'>225</a> <a id='n226' href='#n226'>226</a> <a id='n227' href='#n227'>227</a> <a id='n228' href='#n228'>228</a> <a id='n229' href='#n229'>229</a> <a id='n230' href='#n230'>230</a> <a id='n231' href='#n231'>231</a> <a id='n232' href='#n232'>232</a> <a id='n233' href='#n233'>233</a> <a id='n234' href='#n234'>234</a> <a id='n235' href='#n235'>235</a> <a id='n236' href='#n236'>236</a> <a id='n237' href='#n237'>237</a> <a id='n238' href='#n238'>238</a> <a id='n239' href='#n239'>239</a> <a id='n240' href='#n240'>240</a> <a id='n241' href='#n241'>241</a> <a id='n242' href='#n242'>242</a> <a id='n243' href='#n243'>243</a> <a id='n244' href='#n244'>244</a> <a id='n245' href='#n245'>245</a> <a id='n246' href='#n246'>246</a> <a id='n247' href='#n247'>247</a> <a id='n248' href='#n248'>248</a> <a id='n249' href='#n249'>249</a> <a id='n250' href='#n250'>250</a> <a id='n251' href='#n251'>251</a> <a id='n252' href='#n252'>252</a> <a id='n253' href='#n253'>253</a> <a id='n254' href='#n254'>254</a> <a id='n255' href='#n255'>255</a> <a id='n256' href='#n256'>256</a> <a id='n257' href='#n257'>257</a> <a id='n258' href='#n258'>258</a> <a id='n259' href='#n259'>259</a> <a id='n260' href='#n260'>260</a> <a id='n261' href='#n261'>261</a> <a id='n262' href='#n262'>262</a> <a id='n263' href='#n263'>263</a> <a id='n264' href='#n264'>264</a> <a id='n265' href='#n265'>265</a> <a id='n266' href='#n266'>266</a> <a id='n267' href='#n267'>267</a> <a id='n268' href='#n268'>268</a> <a id='n269' href='#n269'>269</a> <a id='n270' href='#n270'>270</a> <a id='n271' href='#n271'>271</a> <a id='n272' href='#n272'>272</a> <a id='n273' href='#n273'>273</a> <a id='n274' href='#n274'>274</a> <a id='n275' href='#n275'>275</a> <a id='n276' href='#n276'>276</a> <a id='n277' href='#n277'>277</a> <a id='n278' href='#n278'>278</a> <a id='n279' href='#n279'>279</a> <a id='n280' href='#n280'>280</a> <a id='n281' href='#n281'>281</a> <a id='n282' href='#n282'>282</a> <a id='n283' href='#n283'>283</a> <a id='n284' href='#n284'>284</a> <a id='n285' href='#n285'>285</a> <a id='n286' href='#n286'>286</a> <a id='n287' href='#n287'>287</a> <a id='n288' href='#n288'>288</a> <a id='n289' href='#n289'>289</a> <a id='n290' href='#n290'>290</a> <a id='n291' href='#n291'>291</a> <a id='n292' href='#n292'>292</a> <a id='n293' href='#n293'>293</a> <a id='n294' href='#n294'>294</a> <a id='n295' href='#n295'>295</a> <a id='n296' href='#n296'>296</a> <a id='n297' href='#n297'>297</a> <a id='n298' href='#n298'>298</a> <a id='n299' href='#n299'>299</a> <a id='n300' href='#n300'>300</a> <a id='n301' href='#n301'>301</a> <a id='n302' href='#n302'>302</a> <a id='n303' href='#n303'>303</a> <a id='n304' href='#n304'>304</a> <a id='n305' href='#n305'>305</a> <a id='n306' href='#n306'>306</a> <a id='n307' href='#n307'>307</a> <a id='n308' href='#n308'>308</a> <a id='n309' href='#n309'>309</a> <a id='n310' href='#n310'>310</a> <a id='n311' href='#n311'>311</a> <a id='n312' href='#n312'>312</a> <a id='n313' href='#n313'>313</a> <a id='n314' href='#n314'>314</a> <a id='n315' href='#n315'>315</a> <a id='n316' href='#n316'>316</a> <a id='n317' href='#n317'>317</a> <a id='n318' href='#n318'>318</a> <a id='n319' href='#n319'>319</a> <a id='n320' href='#n320'>320</a> <a id='n321' href='#n321'>321</a> <a id='n322' href='#n322'>322</a> <a id='n323' href='#n323'>323</a> <a id='n324' href='#n324'>324</a> <a id='n325' href='#n325'>325</a> <a id='n326' href='#n326'>326</a> <a id='n327' href='#n327'>327</a> <a id='n328' href='#n328'>328</a> <a id='n329' href='#n329'>329</a> <a id='n330' href='#n330'>330</a> <a id='n331' href='#n331'>331</a> <a id='n332' href='#n332'>332</a> <a id='n333' href='#n333'>333</a> <a id='n334' href='#n334'>334</a> <a id='n335' href='#n335'>335</a> <a id='n336' href='#n336'>336</a> <a id='n337' href='#n337'>337</a> <a id='n338' href='#n338'>338</a> <a id='n339' href='#n339'>339</a> <a id='n340' href='#n340'>340</a> <a id='n341' href='#n341'>341</a> <a id='n342' href='#n342'>342</a> <a id='n343' href='#n343'>343</a> <a id='n344' href='#n344'>344</a> <a id='n345' href='#n345'>345</a> <a id='n346' href='#n346'>346</a> <a id='n347' href='#n347'>347</a> <a id='n348' href='#n348'>348</a> <a id='n349' href='#n349'>349</a> <a id='n350' href='#n350'>350</a> <a id='n351' href='#n351'>351</a> <a id='n352' href='#n352'>352</a> <a id='n353' href='#n353'>353</a> <a id='n354' href='#n354'>354</a> <a id='n355' href='#n355'>355</a> <a id='n356' href='#n356'>356</a> <a id='n357' href='#n357'>357</a> <a id='n358' href='#n358'>358</a> <a id='n359' href='#n359'>359</a> <a id='n360' href='#n360'>360</a> <a id='n361' href='#n361'>361</a> <a id='n362' href='#n362'>362</a> <a id='n363' href='#n363'>363</a> <a id='n364' href='#n364'>364</a> <a id='n365' href='#n365'>365</a> <a id='n366' href='#n366'>366</a> <a id='n367' href='#n367'>367</a> <a id='n368' href='#n368'>368</a> <a id='n369' href='#n369'>369</a> <a id='n370' href='#n370'>370</a> <a id='n371' href='#n371'>371</a> <a id='n372' href='#n372'>372</a> <a id='n373' href='#n373'>373</a> <a id='n374' href='#n374'>374</a> <a id='n375' href='#n375'>375</a> <a id='n376' href='#n376'>376</a> <a id='n377' href='#n377'>377</a> <a id='n378' href='#n378'>378</a> <a id='n379' href='#n379'>379</a> <a id='n380' href='#n380'>380</a> <a id='n381' href='#n381'>381</a> <a id='n382' href='#n382'>382</a> <a id='n383' href='#n383'>383</a> <a id='n384' href='#n384'>384</a> <a id='n385' href='#n385'>385</a> <a id='n386' href='#n386'>386</a> <a id='n387' href='#n387'>387</a> <a id='n388' href='#n388'>388</a> <a id='n389' href='#n389'>389</a> <a id='n390' href='#n390'>390</a> <a id='n391' href='#n391'>391</a> <a id='n392' href='#n392'>392</a> <a id='n393' href='#n393'>393</a> <a id='n394' href='#n394'>394</a> <a id='n395' href='#n395'>395</a> <a id='n396' href='#n396'>396</a> <a id='n397' href='#n397'>397</a> <a id='n398' href='#n398'>398</a> <a id='n399' href='#n399'>399</a> <a id='n400' href='#n400'>400</a> <a id='n401' href='#n401'>401</a> <a id='n402' href='#n402'>402</a> <a id='n403' href='#n403'>403</a> <a id='n404' href='#n404'>404</a> <a id='n405' href='#n405'>405</a> <a id='n406' href='#n406'>406</a> <a id='n407' href='#n407'>407</a> <a id='n408' href='#n408'>408</a> <a id='n409' href='#n409'>409</a> <a id='n410' href='#n410'>410</a> <a id='n411' href='#n411'>411</a> <a id='n412' href='#n412'>412</a> <a id='n413' href='#n413'>413</a> <a id='n414' href='#n414'>414</a> <a id='n415' href='#n415'>415</a> <a id='n416' href='#n416'>416</a> <a id='n417' href='#n417'>417</a> <a id='n418' href='#n418'>418</a> <a id='n419' href='#n419'>419</a> <a id='n420' href='#n420'>420</a> <a id='n421' href='#n421'>421</a> <a id='n422' href='#n422'>422</a> <a id='n423' href='#n423'>423</a> <a id='n424' href='#n424'>424</a> <a id='n425' href='#n425'>425</a> <a id='n426' href='#n426'>426</a> <a id='n427' href='#n427'>427</a> <a id='n428' href='#n428'>428</a> <a id='n429' href='#n429'>429</a> <a id='n430' href='#n430'>430</a> <a id='n431' href='#n431'>431</a> <a id='n432' href='#n432'>432</a> <a id='n433' href='#n433'>433</a> <a id='n434' href='#n434'>434</a> <a id='n435' href='#n435'>435</a> <a id='n436' href='#n436'>436</a> <a id='n437' href='#n437'>437</a> <a id='n438' href='#n438'>438</a> <a id='n439' href='#n439'>439</a> <a id='n440' href='#n440'>440</a> <a id='n441' href='#n441'>441</a> <a id='n442' href='#n442'>442</a> <a id='n443' href='#n443'>443</a> <a id='n444' href='#n444'>444</a> <a id='n445' href='#n445'>445</a> <a id='n446' href='#n446'>446</a> <a id='n447' href='#n447'>447</a> <a id='n448' href='#n448'>448</a> <a id='n449' href='#n449'>449</a> <a id='n450' href='#n450'>450</a> <a id='n451' href='#n451'>451</a> <a id='n452' href='#n452'>452</a> <a id='n453' href='#n453'>453</a> <a id='n454' href='#n454'>454</a> <a id='n455' href='#n455'>455</a> <a id='n456' href='#n456'>456</a> <a id='n457' href='#n457'>457</a> <a id='n458' href='#n458'>458</a> <a id='n459' href='#n459'>459</a> <a id='n460' href='#n460'>460</a> <a id='n461' href='#n461'>461</a> <a id='n462' href='#n462'>462</a> <a id='n463' href='#n463'>463</a> <a id='n464' href='#n464'>464</a> <a id='n465' href='#n465'>465</a> <a id='n466' href='#n466'>466</a> <a id='n467' href='#n467'>467</a> </pre></td> <td class='lines'><pre><code><style>pre { line-height: 125%; margin: 0; } td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; } span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; } td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; } .highlight .hll { background-color: #ffffcc } .highlight { background: #ffffff; } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */</style><div class="highlight"><pre><span></span>From 293903b9dfe43520f01374dc1661be11d6838c49 Mon Sep 17 00:00:00 2001 From: Sander Vanheule <sander@svanheule.net> Date: Thu, 18 Nov 2021 17:29:52 +0100 Subject: watchdog: Add Realtek Otto watchdog timer Realtek MIPS SoCs (platform name Otto) have a watchdog timer with pretimeout notifitication support. The WDT can (partially) hard reset, or soft reset the SoC. This driver implements all features as described in the devicetree binding, except the phase2 interrupt, and also functions as a restart handler. The cpu reset mode is considered to be a "warm" restart, since this mode does not reset all peripherals. Being an embedded system though, the "cpu" and "software" modes will still cause the bootloader to run on restart. It is not known how a forced system reset can be disabled on the supported platforms. This means that the phase2 interrupt will only fire at the same time as reset, so implementing phase2 is of little use. Signed-off-by: Sander Vanheule <sander@svanheule.net> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Link: https://lore.kernel.org/r/6d060bccbdcc709cfa79203485db85aad3c3beb5.1637252610.git.sander@svanheule.net Signed-off-by: Guenter Roeck <linux@roeck-us.net> <span class="gd">---</span> MAINTAINERS | 7 + drivers/watchdog/Kconfig | 13 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/realtek_otto_wdt.c | 384 ++++++++++++++++++++++++++++++++++++ 4 files changed, 405 insertions(+) create mode 100644 drivers/watchdog/realtek_otto_wdt.c <span class="gd">--- a/MAINTAINERS</span> <span class="gi">+++ b/MAINTAINERS</span> <span class="gu">@@ -15891,6 +15891,13 @@ S: Maintained</span> F: include/sound/rt*.h F: sound/soc/codecs/rt* <span class="gi">+REALTEK OTTO WATCHDOG</span> <span class="gi">+M: Sander Vanheule <sander@svanheule.net></span> <span class="gi">+L: linux-watchdog@vger.kernel.org</span> <span class="gi">+S: Maintained</span> <span class="gi">+F: Documentation/devicetree/bindings/watchdog/realtek,otto-wdt.yaml</span> <span class="gi">+F: driver/watchdog/realtek_otto_wdt.c</span> <span class="gi">+</span> REALTEK RTL83xx SMI DSA ROUTER CHIPS M: Linus Walleij <linus.walleij@linaro.org> S: Maintained <span class="gd">--- a/drivers/watchdog/Kconfig</span> <span class="gi">+++ b/drivers/watchdog/Kconfig</span> <span class="gu">@@ -954,6 +954,19 @@ config RTD119X_WATCHDOG</span> Say Y here to include support for the watchdog timer in Realtek RTD1295 SoCs. <span class="gi">+config REALTEK_OTTO_WDT</span> <span class="gi">+ tristate "Realtek Otto MIPS watchdog support"</span> <span class="gi">+ depends on MACH_REALTEK_RTL || COMPILE_TEST</span> <span class="gi">+ depends on COMMON_CLK</span> <span class="gi">+ select WATCHDOG_CORE</span> <span class="gi">+ default MACH_REALTEK_RTL</span> <span class="gi">+ help</span> <span class="gi">+ Say Y here to include support for the watchdog timer on Realtek</span> <span class="gi">+ RTL838x, RTL839x, RTL930x SoCs. This watchdog has pretimeout</span> <span class="gi">+ notifications and system reset on timeout.</span> <span class="gi">+</span> <span class="gi">+ When built as a module this will be called realtek_otto_wdt.</span> <span class="gi">+</span> config SPRD_WATCHDOG tristate "Spreadtrum watchdog support" depends on ARCH_SPRD || COMPILE_TEST <span class="gd">--- a/drivers/watchdog/Makefile</span> <span class="gi">+++ b/drivers/watchdog/Makefile</span> <span class="gu">@@ -171,6 +171,7 @@ obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o</span> obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o obj-$(CONFIG_PIC32_WDT) += pic32-wdt.o obj-$(CONFIG_PIC32_DMT) += pic32-dmt.o <span class="gi">+obj-$(CONFIG_REALTEK_OTTO_WDT) += realtek_otto_wdt.o</span> # PARISC Architecture <span class="gd">--- /dev/null</span> <span class="gi">+++ b/drivers/watchdog/realtek_otto_wdt.c</span> <span class="gu">@@ -0,0 +1,384 @@</span> <span class="gi">+// SPDX-License-Identifier: GPL-2.0-only</span> <span class="gi">+</span> <span class="gi">+/*</span> <span class="gi">+ * Realtek Otto MIPS platform watchdog</span> <span class="gi">+ *</span> <span class="gi">+ * Watchdog timer that will reset the system after timeout, using the selected</span> <span class="gi">+ * reset mode.</span> <span class="gi">+ *</span> <span class="gi">+ * Counter scaling and timeouts:</span> <span class="gi">+ * - Base prescale of (2 << 25), providing tick duration T_0: 168ms @ 200MHz</span> <span class="gi">+ * - PRESCALE: logarithmic prescaler adding a factor of {1, 2, 4, 8}</span> <span class="gi">+ * - Phase 1: Times out after (PHASE1 + 1) × PRESCALE × T_0</span> <span class="gi">+ * Generates an interrupt, WDT cannot be stopped after phase 1</span> <span class="gi">+ * - Phase 2: starts after phase 1, times out after (PHASE2 + 1) × PRESCALE × T_0</span> <span class="gi">+ * Resets the system according to RST_MODE</span> <span class="gi">+ */</span> <span class="gi">+</span> <span class="gi">+#include <linux/bits.h></span> <span class="gi">+#include <linux/bitfield.h></span> <span class="gi">+#include <linux/clk.h></span> <span class="gi">+#include <linux/delay.h></span> <span class="gi">+#include <linux/interrupt.h></span> <span class="gi">+#include <linux/io.h></span> <span class="gi">+#include <linux/math.h></span> <span class="gi">+#include <linux/minmax.h></span> <span class="gi">+#include <linux/module.h></span> <span class="gi">+#include <linux/mod_devicetable.h></span> <span class="gi">+#include <linux/platform_device.h></span> <span class="gi">+#include <linux/property.h></span> <span class="gi">+#include <linux/reboot.h></span> <span class="gi">+#include <linux/watchdog.h></span> <span class="gi">+</span> <span class="gi">+#define OTTO_WDT_REG_CNTR 0x0</span> <span class="gi">+#define OTTO_WDT_CNTR_PING BIT(31)</span> <span class="gi">+</span> <span class="gi">+#define OTTO_WDT_REG_INTR 0x4</span> <span class="gi">+#define OTTO_WDT_INTR_PHASE_1 BIT(31)</span> <span class="gi">+#define OTTO_WDT_INTR_PHASE_2 BIT(30)</span> <span class="gi">+</span> <span class="gi">+#define OTTO_WDT_REG_CTRL 0x8</span> <span class="gi">+#define OTTO_WDT_CTRL_ENABLE BIT(31)</span> <span class="gi">+#define OTTO_WDT_CTRL_PRESCALE GENMASK(30, 29)</span> <span class="gi">+#define OTTO_WDT_CTRL_PHASE1 GENMASK(26, 22)</span> <span class="gi">+#define OTTO_WDT_CTRL_PHASE2 GENMASK(19, 15)</span> <span class="gi">+#define OTTO_WDT_CTRL_RST_MODE GENMASK(1, 0)</span> <span class="gi">+#define OTTO_WDT_MODE_SOC 0</span> <span class="gi">+#define OTTO_WDT_MODE_CPU 1</span> <span class="gi">+#define OTTO_WDT_MODE_SOFTWARE 2</span> <span class="gi">+#define OTTO_WDT_CTRL_DEFAULT OTTO_WDT_MODE_CPU</span> <span class="gi">+</span> <span class="gi">+#define OTTO_WDT_PRESCALE_MAX 3</span> <span class="gi">+</span> <span class="gi">+/*</span> <span class="gi">+ * One higher than the max values contained in PHASE{1,2}, since a value of 0</span> <span class="gi">+ * corresponds to one tick.</span> <span class="gi">+ */</span> <span class="gi">+#define OTTO_WDT_PHASE_TICKS_MAX 32</span> <span class="gi">+</span> <span class="gi">+/*</span> <span class="gi">+ * The maximum reset delay is actually 2×32 ticks, but that would require large</span> <span class="gi">+ * pretimeout values for timeouts longer than 32 ticks. Limit the maximum timeout</span> <span class="gi">+ * to 32 + 1 to ensure small pretimeout values can be configured as expected.</span> <span class="gi">+ */</span> <span class="gi">+#define OTTO_WDT_TIMEOUT_TICKS_MAX (OTTO_WDT_PHASE_TICKS_MAX + 1)</span> <span class="gi">+</span> <span class="gi">+struct otto_wdt_ctrl {</span> <span class="gi">+ struct watchdog_device wdev;</span> <span class="gi">+ struct device *dev;</span> <span class="gi">+ void __iomem *base;</span> <span class="gi">+ unsigned int clk_rate_khz;</span> <span class="gi">+ int irq_phase1;</span> <span class="gi">+};</span> <span class="gi">+</span> <span class="gi">+static int otto_wdt_start(struct watchdog_device *wdev)</span> <span class="gi">+{</span> <span class="gi">+ struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);</span> <span class="gi">+ u32 v;</span> <span class="gi">+</span> <span class="gi">+ v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL);</span> <span class="gi">+ v |= OTTO_WDT_CTRL_ENABLE;</span> <span class="gi">+ iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);</span> <span class="gi">+</span> <span class="gi">+ return 0;</span> <span class="gi">+}</span> <span class="gi">+</span> <span class="gi">+static int otto_wdt_stop(struct watchdog_device *wdev)</span> <span class="gi">+{</span> <span class="gi">+ struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);</span> <span class="gi">+ u32 v;</span> <span class="gi">+</span> <span class="gi">+ v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL);</span> <span class="gi">+ v &= ~OTTO_WDT_CTRL_ENABLE;</span> <span class="gi">+ iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);</span> <span class="gi">+</span> <span class="gi">+ return 0;</span> <span class="gi">+}</span> <span class="gi">+</span> <span class="gi">+static int otto_wdt_ping(struct watchdog_device *wdev)</span> <span class="gi">+{</span> <span class="gi">+ struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);</span> <span class="gi">+</span> <span class="gi">+ iowrite32(OTTO_WDT_CNTR_PING, ctrl->base + OTTO_WDT_REG_CNTR);</span> <span class="gi">+</span> <span class="gi">+ return 0;</span> <span class="gi">+}</span> <span class="gi">+</span> <span class="gi">+static int otto_wdt_tick_ms(struct otto_wdt_ctrl *ctrl, int prescale)</span> <span class="gi">+{</span> <span class="gi">+ return DIV_ROUND_CLOSEST(1 << (25 + prescale), ctrl->clk_rate_khz);</span> <span class="gi">+}</span> <span class="gi">+</span> <span class="gi">+/*</span> <span class="gi">+ * The timer asserts the PHASE1/PHASE2 IRQs when the number of ticks exceeds</span> <span class="gi">+ * the value stored in those fields. This means each phase will run for at least</span> <span class="gi">+ * one tick, so small values need to be clamped to correctly reflect the timeout.</span> <span class="gi">+ */</span> <span class="gi">+static inline unsigned int div_round_ticks(unsigned int val, unsigned int tick_duration,</span> <span class="gi">+ unsigned int min_ticks)</span> <span class="gi">+{</span> <span class="gi">+ return max(min_ticks, DIV_ROUND_UP(val, tick_duration));</span> <span class="gi">+}</span> <span class="gi">+</span> <span class="gi">+static int otto_wdt_determine_timeouts(struct watchdog_device *wdev, unsigned int timeout,</span> <span class="gi">+ unsigned int pretimeout)</span> <span class="gi">+{</span> <span class="gi">+ struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);</span> <span class="gi">+ unsigned int pretimeout_ms = pretimeout * 1000;</span> <span class="gi">+ unsigned int timeout_ms = timeout * 1000;</span> <span class="gi">+ unsigned int prescale_next = 0;</span> <span class="gi">+ unsigned int phase1_ticks;</span> <span class="gi">+ unsigned int phase2_ticks;</span> <span class="gi">+ unsigned int total_ticks;</span> <span class="gi">+ unsigned int prescale;</span> <span class="gi">+ unsigned int tick_ms;</span> <span class="gi">+ u32 v;</span> <span class="gi">+</span> <span class="gi">+ do {</span> <span class="gi">+ prescale = prescale_next;</span> <span class="gi">+ if (prescale > OTTO_WDT_PRESCALE_MAX)</span> <span class="gi">+ return -EINVAL;</span> <span class="gi">+</span> <span class="gi">+ tick_ms = otto_wdt_tick_ms(ctrl, prescale);</span> <span class="gi">+ total_ticks = div_round_ticks(timeout_ms, tick_ms, 2);</span> <span class="gi">+ phase1_ticks = div_round_ticks(timeout_ms - pretimeout_ms, tick_ms, 1);</span> <span class="gi">+ phase2_ticks = total_ticks - phase1_ticks;</span> <span class="gi">+</span> <span class="gi">+ prescale_next++;</span> <span class="gi">+ } while (phase1_ticks > OTTO_WDT_PHASE_TICKS_MAX</span> <span class="gi">+ || phase2_ticks > OTTO_WDT_PHASE_TICKS_MAX);</span> <span class="gi">+</span> <span class="gi">+ v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL);</span> <span class="gi">+</span> <span class="gi">+ v &= ~(OTTO_WDT_CTRL_PRESCALE | OTTO_WDT_CTRL_PHASE1 | OTTO_WDT_CTRL_PHASE2);</span> <span class="gi">+ v |= FIELD_PREP(OTTO_WDT_CTRL_PHASE1, phase1_ticks - 1);</span> <span class="gi">+ v |= FIELD_PREP(OTTO_WDT_CTRL_PHASE2, phase2_ticks - 1);</span> <span class="gi">+ v |= FIELD_PREP(OTTO_WDT_CTRL_PRESCALE, prescale);</span> <span class="gi">+</span> <span class="gi">+ iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);</span> <span class="gi">+</span> <span class="gi">+ timeout_ms = total_ticks * tick_ms;</span> <span class="gi">+ ctrl->wdev.timeout = timeout_ms / 1000;</span> <span class="gi">+</span> <span class="gi">+ pretimeout_ms = phase2_ticks * tick_ms;</span> <span class="gi">+ ctrl->wdev.pretimeout = pretimeout_ms / 1000;</span> <span class="gi">+</span> <span class="gi">+ return 0;</span> <span class="gi">+}</span> <span class="gi">+</span> <span class="gi">+static int otto_wdt_set_timeout(struct watchdog_device *wdev, unsigned int val)</span> <span class="gi">+{</span> <span class="gi">+ return otto_wdt_determine_timeouts(wdev, val, min(wdev->pretimeout, val - 1));</span> <span class="gi">+}</span> <span class="gi">+</span> <span class="gi">+static int otto_wdt_set_pretimeout(struct watchdog_device *wdev, unsigned int val)</span> <span class="gi">+{</span> <span class="gi">+ return otto_wdt_determine_timeouts(wdev, wdev->timeout, val);</span> <span class="gi">+}</span> <span class="gi">+</span> <span class="gi">+static int otto_wdt_restart(struct watchdog_device *wdev, unsigned long reboot_mode,</span> <span class="gi">+ void *data)</span> <span class="gi">+{</span> <span class="gi">+ struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);</span> <span class="gi">+ u32 reset_mode;</span> <span class="gi">+ u32 v;</span> <span class="gi">+</span> <span class="gi">+ disable_irq(ctrl->irq_phase1);</span> <span class="gi">+</span> <span class="gi">+ switch (reboot_mode) {</span> <span class="gi">+ case REBOOT_SOFT:</span> <span class="gi">+ reset_mode = OTTO_WDT_MODE_SOFTWARE;</span> <span class="gi">+ break;</span> <span class="gi">+ case REBOOT_WARM:</span> <span class="gi">+ reset_mode = OTTO_WDT_MODE_CPU;</span> <span class="gi">+ break;</span> <span class="gi">+ default:</span> <span class="gi">+ reset_mode = OTTO_WDT_MODE_SOC;</span> <span class="gi">+ break;</span> <span class="gi">+ }</span> <span class="gi">+</span> <span class="gi">+ /* Configure for shortest timeout and wait for reset to occur */</span> <span class="gi">+ v = FIELD_PREP(OTTO_WDT_CTRL_RST_MODE, reset_mode) | OTTO_WDT_CTRL_ENABLE;</span> <span class="gi">+ iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);</span> <span class="gi">+</span> <span class="gi">+ mdelay(3 * otto_wdt_tick_ms(ctrl, 0));</span> <span class="gi">+</span> <span class="gi">+ return 0;</span> <span class="gi">+}</span> <span class="gi">+</span> <span class="gi">+static irqreturn_t otto_wdt_phase1_isr(int irq, void *dev_id)</span> <span class="gi">+{</span> <span class="gi">+ struct otto_wdt_ctrl *ctrl = dev_id;</span> <span class="gi">+</span> <span class="gi">+ iowrite32(OTTO_WDT_INTR_PHASE_1, ctrl->base + OTTO_WDT_REG_INTR);</span> <span class="gi">+ dev_crit(ctrl->dev, "phase 1 timeout\n");</span> <span class="gi">+ watchdog_notify_pretimeout(&ctrl->wdev);</span> <span class="gi">+</span> <span class="gi">+ return IRQ_HANDLED;</span> <span class="gi">+}</span> <span class="gi">+</span> <span class="gi">+static const struct watchdog_ops otto_wdt_ops = {</span> <span class="gi">+ .owner = THIS_MODULE,</span> <span class="gi">+ .start = otto_wdt_start,</span> <span class="gi">+ .stop = otto_wdt_stop,</span> <span class="gi">+ .ping = otto_wdt_ping,</span> <span class="gi">+ .set_timeout = otto_wdt_set_timeout,</span> <span class="gi">+ .set_pretimeout = otto_wdt_set_pretimeout,</span> <span class="gi">+ .restart = otto_wdt_restart,</span> <span class="gi">+};</span> <span class="gi">+</span> <span class="gi">+static const struct watchdog_info otto_wdt_info = {</span> <span class="gi">+ .identity = "Realtek Otto watchdog timer",</span> <span class="gi">+ .options = WDIOF_KEEPALIVEPING |</span> <span class="gi">+ WDIOF_MAGICCLOSE |</span> <span class="gi">+ WDIOF_SETTIMEOUT |</span> <span class="gi">+ WDIOF_PRETIMEOUT,</span> <span class="gi">+};</span> <span class="gi">+</span> <span class="gi">+static void otto_wdt_clock_action(void *data)</span> <span class="gi">+{</span> <span class="gi">+ clk_disable_unprepare(data);</span> <span class="gi">+}</span> <span class="gi">+</span> <span class="gi">+static int otto_wdt_probe_clk(struct otto_wdt_ctrl *ctrl)</span> <span class="gi">+{</span> <span class="gi">+ struct clk *clk = devm_clk_get(ctrl->dev, NULL);</span> <span class="gi">+ int ret;</span> <span class="gi">+</span> <span class="gi">+ if (IS_ERR(clk))</span> <span class="gi">+ return dev_err_probe(ctrl->dev, PTR_ERR(clk), "Failed to get clock\n");</span> <span class="gi">+</span> <span class="gi">+ ret = clk_prepare_enable(clk);</span> <span class="gi">+ if (ret)</span> <span class="gi">+ return dev_err_probe(ctrl->dev, ret, "Failed to enable clock\n");</span> <span class="gi">+</span> <span class="gi">+ ret = devm_add_action_or_reset(ctrl->dev, otto_wdt_clock_action, clk);</span> <span class="gi">+ if (ret)</span> <span class="gi">+ return ret;</span> <span class="gi">+</span> <span class="gi">+ ctrl->clk_rate_khz = clk_get_rate(clk) / 1000;</span> <span class="gi">+ if (ctrl->clk_rate_khz == 0)</span> <span class="gi">+ return dev_err_probe(ctrl->dev, -ENXIO, "Failed to get clock rate\n");</span> <span class="gi">+</span> <span class="gi">+ return 0;</span> <span class="gi">+}</span> <span class="gi">+</span> <span class="gi">+static int otto_wdt_probe_reset_mode(struct otto_wdt_ctrl *ctrl)</span> <span class="gi">+{</span> <span class="gi">+ static const char *mode_property = "realtek,reset-mode";</span> <span class="gi">+ const struct fwnode_handle *node = ctrl->dev->fwnode;</span> <span class="gi">+ int mode_count;</span> <span class="gi">+ u32 mode;</span> <span class="gi">+ u32 v;</span> <span class="gi">+</span> <span class="gi">+ if (!node)</span> <span class="gi">+ return -ENXIO;</span> <span class="gi">+</span> <span class="gi">+ mode_count = fwnode_property_string_array_count(node, mode_property);</span> <span class="gi">+ if (mode_count < 0)</span> <span class="gi">+ return mode_count;</span> <span class="gi">+ else if (mode_count == 0)</span> <span class="gi">+ return 0;</span> <span class="gi">+ else if (mode_count != 1)</span> <span class="gi">+ return -EINVAL;</span> <span class="gi">+</span> <span class="gi">+ if (fwnode_property_match_string(node, mode_property, "soc") == 0)</span> <span class="gi">+ mode = OTTO_WDT_MODE_SOC;</span> <span class="gi">+ else if (fwnode_property_match_string(node, mode_property, "cpu") == 0)</span> <span class="gi">+ mode = OTTO_WDT_MODE_CPU;</span> <span class="gi">+ else if (fwnode_property_match_string(node, mode_property, "software") == 0)</span> <span class="gi">+ mode = OTTO_WDT_MODE_SOFTWARE;</span> <span class="gi">+ else</span> <span class="gi">+ return -EINVAL;</span> <span class="gi">+</span> <span class="gi">+ v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL);</span> <span class="gi">+ v &= ~OTTO_WDT_CTRL_RST_MODE;</span> <span class="gi">+ v |= FIELD_PREP(OTTO_WDT_CTRL_RST_MODE, mode);</span> <span class="gi">+ iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);</span> <span class="gi">+</span> <span class="gi">+ return 0;</span> <span class="gi">+}</span> <span class="gi">+</span> <span class="gi">+static int otto_wdt_probe(struct platform_device *pdev)</span> <span class="gi">+{</span> <span class="gi">+ struct device *dev = &pdev->dev;</span> <span class="gi">+ struct otto_wdt_ctrl *ctrl;</span> <span class="gi">+ unsigned int max_tick_ms;</span> <span class="gi">+ int ret;</span> <span class="gi">+</span> <span class="gi">+ ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);</span> <span class="gi">+ if (!ctrl)</span> <span class="gi">+ return -ENOMEM;</span> <span class="gi">+</span> <span class="gi">+ ctrl->dev = dev;</span> <span class="gi">+ ctrl->base = devm_platform_ioremap_resource(pdev, 0);</span> <span class="gi">+ if (IS_ERR(ctrl->base))</span> <span class="gi">+ return PTR_ERR(ctrl->base);</span> <span class="gi">+</span> <span class="gi">+ /* Clear any old interrupts and reset initial state */</span> <span class="gi">+ iowrite32(OTTO_WDT_INTR_PHASE_1 | OTTO_WDT_INTR_PHASE_2,</span> <span class="gi">+ ctrl->base + OTTO_WDT_REG_INTR);</span> <span class="gi">+ iowrite32(OTTO_WDT_CTRL_DEFAULT, ctrl->base + OTTO_WDT_REG_CTRL);</span> <span class="gi">+</span> <span class="gi">+ ret = otto_wdt_probe_clk(ctrl);</span> <span class="gi">+ if (ret)</span> <span class="gi">+ return ret;</span> <span class="gi">+</span> <span class="gi">+ ctrl->irq_phase1 = platform_get_irq_byname(pdev, "phase1");</span> <span class="gi">+ if (ctrl->irq_phase1 < 0)</span> <span class="gi">+ return ctrl->irq_phase1;</span> <span class="gi">+</span> <span class="gi">+ ret = devm_request_irq(dev, ctrl->irq_phase1, otto_wdt_phase1_isr, 0,</span> <span class="gi">+ "realtek-otto-wdt", ctrl);</span> <span class="gi">+ if (ret)</span> <span class="gi">+ return dev_err_probe(dev, ret, "Failed to get IRQ for phase1\n");</span> <span class="gi">+</span> <span class="gi">+ ret = otto_wdt_probe_reset_mode(ctrl);</span> <span class="gi">+ if (ret)</span> <span class="gi">+ return dev_err_probe(dev, ret, "Invalid reset mode specified\n");</span> <span class="gi">+</span> <span class="gi">+ ctrl->wdev.parent = dev;</span> <span class="gi">+ ctrl->wdev.info = &otto_wdt_info;</span> <span class="gi">+ ctrl->wdev.ops = &otto_wdt_ops;</span> <span class="gi">+</span> <span class="gi">+ /*</span> <span class="gi">+ * Since pretimeout cannot be disabled, min. timeout is twice the</span> <span class="gi">+ * subsystem resolution. Max. timeout is ca. 43s at a bus clock of 200MHz.</span> <span class="gi">+ */</span> <span class="gi">+ ctrl->wdev.min_timeout = 2;</span> <span class="gi">+ max_tick_ms = otto_wdt_tick_ms(ctrl, OTTO_WDT_PRESCALE_MAX);</span> <span class="gi">+ ctrl->wdev.max_hw_heartbeat_ms = max_tick_ms * OTTO_WDT_TIMEOUT_TICKS_MAX;</span> <span class="gi">+ ctrl->wdev.timeout = min(30U, ctrl->wdev.max_hw_heartbeat_ms / 1000);</span> <span class="gi">+</span> <span class="gi">+ watchdog_set_drvdata(&ctrl->wdev, ctrl);</span> <span class="gi">+ watchdog_init_timeout(&ctrl->wdev, 0, dev);</span> <span class="gi">+ watchdog_stop_on_reboot(&ctrl->wdev);</span> <span class="gi">+ watchdog_set_restart_priority(&ctrl->wdev, 128);</span> <span class="gi">+</span> <span class="gi">+ ret = otto_wdt_determine_timeouts(&ctrl->wdev, ctrl->wdev.timeout, 1);</span> <span class="gi">+ if (ret)</span> <span class="gi">+ return dev_err_probe(dev, ret, "Failed to set timeout\n");</span> <span class="gi">+</span> <span class="gi">+ return devm_watchdog_register_device(dev, &ctrl->wdev);</span> <span class="gi">+}</span> <span class="gi">+</span> <span class="gi">+static const struct of_device_id otto_wdt_ids[] = {</span> <span class="gi">+ { .compatible = "realtek,rtl8380-wdt" },</span> <span class="gi">+ { .compatible = "realtek,rtl8390-wdt" },</span> <span class="gi">+ { .compatible = "realtek,rtl9300-wdt" },</span> <span class="gi">+ { }</span> <span class="gi">+};</span> <span class="gi">+MODULE_DEVICE_TABLE(of, otto_wdt_ids);</span> <span class="gi">+</span> <span class="gi">+static struct platform_driver otto_wdt_driver = {</span> <span class="gi">+ .probe = otto_wdt_probe,</span> <span class="gi">+ .driver = {</span> <span class="gi">+ .name = "realtek-otto-watchdog",</span> <span class="gi">+ .of_match_table = otto_wdt_ids,</span> <span class="gi">+ },</span> <span class="gi">+};</span> <span class="gi">+module_platform_driver(otto_wdt_driver);</span> <span class="gi">+</span> <span class="gi">+MODULE_LICENSE("GPL v2");</span> <span class="gi">+MODULE_AUTHOR("Sander Vanheule <sander@svanheule.net>");</span> <span class="gi">+MODULE_DESCRIPTION("Realtek Otto watchdog timer driver");</span> </pre></div> </code></pre></td></tr></table> </div> <!-- class=content --> <div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit v1.2.3</a> (<a href='https://git-scm.com/'>git 2.25.1</a>) at 2025-03-28 00:55:39 +0000</div> </div> <!-- id=cgit --> </body> </html>