Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'sunxi-clocks-for-3.20' of https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux into clk-next

Allwinner clock changes for 3.20

The set of clock changes for the 3.20 merge window, with mostly:
- Some PLL fixes for the A80 and A31
- The MMC custom phase functions are removed, and moved over to the generic
phase API.
- Add the A80 MMC clocks

Some DT changes slipped here as well, to preserve bisectability.

+1087 -326
+36 -7
Documentation/devicetree/bindings/clock/sunxi.txt
··· 26 26 "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s 27 27 "allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20 28 28 "allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31 29 - "allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31 29 + "allwinner,sun6i-a31-ahb1-clk" - for the AHB1 clock on A31 30 30 "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31 31 31 "allwinner,sun8i-a23-ahb1-gates-clk" - for the AHB1 gates on A23 32 32 "allwinner,sun9i-a80-ahb0-gates-clk" - for the AHB0 gates on A80 ··· 55 55 "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 56 56 "allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23 57 57 "allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13 58 - "allwinner,sun4i-a10-mmc-output-clk" - for the MMC output clock on A10 59 - "allwinner,sun4i-a10-mmc-sample-clk" - for the MMC sample clock on A10 58 + "allwinner,sun4i-a10-mmc-clk" - for the MMC clock 59 + "allwinner,sun9i-a80-mmc-clk" - for mmc module clocks on A80 60 + "allwinner,sun9i-a80-mmc-config-clk" - for mmc gates + resets on A80 60 61 "allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks 62 + "allwinner,sun9i-a80-mod0-clk" - for module 0 (storage) clocks on A80 61 63 "allwinner,sun8i-a23-mbus-clk" - for the MBUS clock on A23 62 64 "allwinner,sun7i-a20-out-clk" - for the external output clocks 63 65 "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31 ··· 75 73 - #clock-cells : from common clock binding; shall be set to 0 except for 76 74 the following compatibles where it shall be set to 1: 77 75 "allwinner,*-gates-clk", "allwinner,sun4i-pll5-clk", 78 - "allwinner,sun4i-pll6-clk", "allwinner,sun6i-a31-pll6-clk" 76 + "allwinner,sun4i-pll6-clk", "allwinner,sun6i-a31-pll6-clk", 77 + "allwinner,*-usb-clk", "allwinner,*-mmc-clk", 78 + "allwinner,*-mmc-config-clk" 79 79 - clock-output-names : shall be the corresponding names of the outputs. 80 80 If the clock module only has one output, the name shall be the 81 81 module name. 82 82 83 83 And "allwinner,*-usb-clk" clocks also require: 84 84 - reset-cells : shall be set to 1 85 + 86 + The "allwinner,sun9i-a80-mmc-config-clk" clock also requires: 87 + - #reset-cells : shall be set to 1 88 + - resets : shall be the reset control phandle for the mmc block. 85 89 86 90 For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate 87 91 dummy clocks at 25 MHz and 125 MHz, respectively. See example. ··· 102 94 For "allwinner,sun6i-a31-pll6-clk", there are 2 outputs. The first output 103 95 is the normal PLL6 output, or "pll6". The second output is rate doubled 104 96 PLL6, or "pll6x2". 97 + 98 + The "allwinner,*-mmc-clk" clocks have three different outputs: the 99 + main clock, with the ID 0, and the output and sample clocks, with the 100 + IDs 1 and 2, respectively. 101 + 102 + The "allwinner,sun9i-a80-mmc-config-clk" clock has one clock/reset output 103 + per mmc controller. The number of outputs is determined by the size of 104 + the address block, which is related to the overall mmc block. 105 105 106 106 For example: 107 107 ··· 154 138 }; 155 139 156 140 mmc0_clk: clk@01c20088 { 157 - #clock-cells = <0>; 158 - compatible = "allwinner,sun4i-mod0-clk"; 141 + #clock-cells = <1>; 142 + compatible = "allwinner,sun4i-a10-mmc-clk"; 159 143 reg = <0x01c20088 0x4>; 160 144 clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; 161 - clock-output-names = "mmc0"; 145 + clock-output-names = "mmc0", "mmc0_output", "mmc0_sample"; 162 146 }; 163 147 164 148 mii_phy_tx_clk: clk@2 { ··· 185 169 */ 186 170 clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>; 187 171 clock-output-names = "gmac"; 172 + }; 173 + 174 + mmc_config_clk: clk@01c13000 { 175 + compatible = "allwinner,sun9i-a80-mmc-config-clk"; 176 + reg = <0x01c13000 0x10>; 177 + clocks = <&ahb0_gates 8>; 178 + clock-names = "ahb"; 179 + resets = <&ahb0_resets 8>; 180 + reset-names = "ahb"; 181 + #clock-cells = <1>; 182 + #reset-cells = <1>; 183 + clock-output-names = "mmc0_config", "mmc1_config", 184 + "mmc2_config", "mmc3_config"; 188 185 };
+4 -4
Documentation/devicetree/bindings/mmc/sunxi-mmc.txt
··· 10 10 Required properties: 11 11 - compatible : "allwinner,sun4i-a10-mmc" or "allwinner,sun5i-a13-mmc" 12 12 - reg : mmc controller base registers 13 - - clocks : a list with 2 phandle + clock specifier pairs 14 - - clock-names : must contain "ahb" and "mmc" 13 + - clocks : a list with 4 phandle + clock specifier pairs 14 + - clock-names : must contain "ahb", "mmc", "output" and "sample" 15 15 - interrupts : mmc controller interrupt 16 16 17 17 Optional properties: ··· 25 25 mmc0: mmc@01c0f000 { 26 26 compatible = "allwinner,sun5i-a13-mmc"; 27 27 reg = <0x01c0f000 0x1000>; 28 - clocks = <&ahb_gates 8>, <&mmc0_clk>; 29 - clock-names = "ahb", "mod"; 28 + clocks = <&ahb_gates 8>, <&mmc0_clk>, <&mmc0_output_clk>, <&mmc0_sample_clk>; 29 + clock-names = "ahb", "mod", "output", "sample"; 30 30 interrupts = <0 32 4>; 31 31 status = "disabled"; 32 32 };
+52 -20
arch/arm/boot/dts/sun4i-a10.dtsi
··· 226 226 }; 227 227 228 228 mmc0_clk: clk@01c20088 { 229 - #clock-cells = <0>; 230 - compatible = "allwinner,sun4i-a10-mod0-clk"; 229 + #clock-cells = <1>; 230 + compatible = "allwinner,sun4i-a10-mmc-clk"; 231 231 reg = <0x01c20088 0x4>; 232 232 clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; 233 - clock-output-names = "mmc0"; 233 + clock-output-names = "mmc0", 234 + "mmc0_output", 235 + "mmc0_sample"; 234 236 }; 235 237 236 238 mmc1_clk: clk@01c2008c { 237 - #clock-cells = <0>; 238 - compatible = "allwinner,sun4i-a10-mod0-clk"; 239 + #clock-cells = <1>; 240 + compatible = "allwinner,sun4i-a10-mmc-clk"; 239 241 reg = <0x01c2008c 0x4>; 240 242 clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; 241 - clock-output-names = "mmc1"; 243 + clock-output-names = "mmc1", 244 + "mmc1_output", 245 + "mmc1_sample"; 242 246 }; 243 247 244 248 mmc2_clk: clk@01c20090 { 245 - #clock-cells = <0>; 246 - compatible = "allwinner,sun4i-a10-mod0-clk"; 249 + #clock-cells = <1>; 250 + compatible = "allwinner,sun4i-a10-mmc-clk"; 247 251 reg = <0x01c20090 0x4>; 248 252 clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; 249 - clock-output-names = "mmc2"; 253 + clock-output-names = "mmc2", 254 + "mmc2_output", 255 + "mmc2_sample"; 250 256 }; 251 257 252 258 mmc3_clk: clk@01c20094 { 253 - #clock-cells = <0>; 254 - compatible = "allwinner,sun4i-a10-mod0-clk"; 259 + #clock-cells = <1>; 260 + compatible = "allwinner,sun4i-a10-mmc-clk"; 255 261 reg = <0x01c20094 0x4>; 256 262 clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; 257 - clock-output-names = "mmc3"; 263 + clock-output-names = "mmc3", 264 + "mmc3_output", 265 + "mmc3_sample"; 258 266 }; 259 267 260 268 ts_clk: clk@01c20098 { ··· 406 398 mmc0: mmc@01c0f000 { 407 399 compatible = "allwinner,sun4i-a10-mmc"; 408 400 reg = <0x01c0f000 0x1000>; 409 - clocks = <&ahb_gates 8>, <&mmc0_clk>; 410 - clock-names = "ahb", "mmc"; 401 + clocks = <&ahb_gates 8>, 402 + <&mmc0_clk 0>, 403 + <&mmc0_clk 1>, 404 + <&mmc0_clk 2>; 405 + clock-names = "ahb", 406 + "mmc", 407 + "output", 408 + "sample"; 411 409 interrupts = <32>; 412 410 status = "disabled"; 413 411 }; ··· 421 407 mmc1: mmc@01c10000 { 422 408 compatible = "allwinner,sun4i-a10-mmc"; 423 409 reg = <0x01c10000 0x1000>; 424 - clocks = <&ahb_gates 9>, <&mmc1_clk>; 425 - clock-names = "ahb", "mmc"; 410 + clocks = <&ahb_gates 9>, 411 + <&mmc1_clk 0>, 412 + <&mmc1_clk 1>, 413 + <&mmc1_clk 2>; 414 + clock-names = "ahb", 415 + "mmc", 416 + "output", 417 + "sample"; 426 418 interrupts = <33>; 427 419 status = "disabled"; 428 420 }; ··· 436 416 mmc2: mmc@01c11000 { 437 417 compatible = "allwinner,sun4i-a10-mmc"; 438 418 reg = <0x01c11000 0x1000>; 439 - clocks = <&ahb_gates 10>, <&mmc2_clk>; 440 - clock-names = "ahb", "mmc"; 419 + clocks = <&ahb_gates 10>, 420 + <&mmc2_clk 0>, 421 + <&mmc2_clk 1>, 422 + <&mmc2_clk 2>; 423 + clock-names = "ahb", 424 + "mmc", 425 + "output", 426 + "sample"; 441 427 interrupts = <34>; 442 428 status = "disabled"; 443 429 }; ··· 451 425 mmc3: mmc@01c12000 { 452 426 compatible = "allwinner,sun4i-a10-mmc"; 453 427 reg = <0x01c12000 0x1000>; 454 - clocks = <&ahb_gates 11>, <&mmc3_clk>; 455 - clock-names = "ahb", "mmc"; 428 + clocks = <&ahb_gates 11>, 429 + <&mmc3_clk 0>, 430 + <&mmc3_clk 1>, 431 + <&mmc3_clk 2>; 432 + clock-names = "ahb", 433 + "mmc", 434 + "output", 435 + "sample"; 456 436 interrupts = <35>; 457 437 status = "disabled"; 458 438 };
+39 -15
arch/arm/boot/dts/sun5i-a10s.dtsi
··· 211 211 }; 212 212 213 213 mmc0_clk: clk@01c20088 { 214 - #clock-cells = <0>; 215 - compatible = "allwinner,sun4i-a10-mod0-clk"; 214 + #clock-cells = <1>; 215 + compatible = "allwinner,sun4i-a10-mmc-clk"; 216 216 reg = <0x01c20088 0x4>; 217 217 clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; 218 - clock-output-names = "mmc0"; 218 + clock-output-names = "mmc0", 219 + "mmc0_output", 220 + "mmc0_sample"; 219 221 }; 220 222 221 223 mmc1_clk: clk@01c2008c { 222 - #clock-cells = <0>; 223 - compatible = "allwinner,sun4i-a10-mod0-clk"; 224 + #clock-cells = <1>; 225 + compatible = "allwinner,sun4i-a10-mmc-clk"; 224 226 reg = <0x01c2008c 0x4>; 225 227 clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; 226 - clock-output-names = "mmc1"; 228 + clock-output-names = "mmc1", 229 + "mmc1_output", 230 + "mmc1_sample"; 227 231 }; 228 232 229 233 mmc2_clk: clk@01c20090 { 230 - #clock-cells = <0>; 231 - compatible = "allwinner,sun4i-a10-mod0-clk"; 234 + #clock-cells = <1>; 235 + compatible = "allwinner,sun4i-a10-mmc-clk"; 232 236 reg = <0x01c20090 0x4>; 233 237 clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; 234 - clock-output-names = "mmc2"; 238 + clock-output-names = "mmc2", 239 + "mmc2_output", 240 + "mmc2_sample"; 235 241 }; 236 242 237 243 ts_clk: clk@01c20098 { ··· 365 359 mmc0: mmc@01c0f000 { 366 360 compatible = "allwinner,sun5i-a13-mmc"; 367 361 reg = <0x01c0f000 0x1000>; 368 - clocks = <&ahb_gates 8>, <&mmc0_clk>; 369 - clock-names = "ahb", "mmc"; 362 + clocks = <&ahb_gates 8>, 363 + <&mmc0_clk 0>, 364 + <&mmc0_clk 1>, 365 + <&mmc0_clk 2>; 366 + clock-names = "ahb", 367 + "mmc", 368 + "output", 369 + "sample"; 370 370 interrupts = <32>; 371 371 status = "disabled"; 372 372 }; ··· 380 368 mmc1: mmc@01c10000 { 381 369 compatible = "allwinner,sun5i-a13-mmc"; 382 370 reg = <0x01c10000 0x1000>; 383 - clocks = <&ahb_gates 9>, <&mmc1_clk>; 384 - clock-names = "ahb", "mmc"; 371 + clocks = <&ahb_gates 9>, 372 + <&mmc1_clk 0>, 373 + <&mmc1_clk 1>, 374 + <&mmc1_clk 2>; 375 + clock-names = "ahb", 376 + "mmc", 377 + "output", 378 + "sample"; 385 379 interrupts = <33>; 386 380 status = "disabled"; 387 381 }; ··· 395 377 mmc2: mmc@01c11000 { 396 378 compatible = "allwinner,sun5i-a13-mmc"; 397 379 reg = <0x01c11000 0x1000>; 398 - clocks = <&ahb_gates 10>, <&mmc2_clk>; 399 - clock-names = "ahb", "mmc"; 380 + clocks = <&ahb_gates 10>, 381 + <&mmc2_clk 0>, 382 + <&mmc2_clk 1>, 383 + <&mmc2_clk 2>; 384 + clock-names = "ahb", 385 + "mmc", 386 + "output", 387 + "sample"; 400 388 interrupts = <34>; 401 389 status = "disabled"; 402 390 };
+31 -13
arch/arm/boot/dts/sun5i-a13.dtsi
··· 195 195 }; 196 196 197 197 mmc0_clk: clk@01c20088 { 198 - #clock-cells = <0>; 199 - compatible = "allwinner,sun4i-a10-mod0-clk"; 198 + #clock-cells = <1>; 199 + compatible = "allwinner,sun4i-a10-mmc-clk"; 200 200 reg = <0x01c20088 0x4>; 201 201 clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; 202 - clock-output-names = "mmc0"; 202 + clock-output-names = "mmc0", 203 + "mmc0_output", 204 + "mmc0_sample"; 203 205 }; 204 206 205 207 mmc1_clk: clk@01c2008c { 206 - #clock-cells = <0>; 207 - compatible = "allwinner,sun4i-a10-mod0-clk"; 208 + #clock-cells = <1>; 209 + compatible = "allwinner,sun4i-a10-mmc-clk"; 208 210 reg = <0x01c2008c 0x4>; 209 211 clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; 210 - clock-output-names = "mmc1"; 212 + clock-output-names = "mmc1", 213 + "mmc1_output", 214 + "mmc1_sample"; 211 215 }; 212 216 213 217 mmc2_clk: clk@01c20090 { 214 - #clock-cells = <0>; 215 - compatible = "allwinner,sun4i-a10-mod0-clk"; 218 + #clock-cells = <1>; 219 + compatible = "allwinner,sun4i-a10-mmc-clk"; 216 220 reg = <0x01c20090 0x4>; 217 221 clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; 218 - clock-output-names = "mmc2"; 222 + clock-output-names = "mmc2", 223 + "mmc2_output", 224 + "mmc2_sample"; 219 225 }; 220 226 221 227 ts_clk: clk@01c20098 { ··· 333 327 mmc0: mmc@01c0f000 { 334 328 compatible = "allwinner,sun5i-a13-mmc"; 335 329 reg = <0x01c0f000 0x1000>; 336 - clocks = <&ahb_gates 8>, <&mmc0_clk>; 337 - clock-names = "ahb", "mmc"; 330 + clocks = <&ahb_gates 8>, 331 + <&mmc0_clk 0>, 332 + <&mmc0_clk 1>, 333 + <&mmc0_clk 2>; 334 + clock-names = "ahb", 335 + "mmc", 336 + "output", 337 + "sample"; 338 338 interrupts = <32>; 339 339 status = "disabled"; 340 340 }; ··· 348 336 mmc2: mmc@01c11000 { 349 337 compatible = "allwinner,sun5i-a13-mmc"; 350 338 reg = <0x01c11000 0x1000>; 351 - clocks = <&ahb_gates 10>, <&mmc2_clk>; 352 - clock-names = "ahb", "mmc"; 339 + clocks = <&ahb_gates 10>, 340 + <&mmc2_clk 0>, 341 + <&mmc2_clk 1>, 342 + <&mmc2_clk 2>; 343 + clock-names = "ahb", 344 + "mmc", 345 + "output", 346 + "sample"; 353 347 interrupts = <34>; 354 348 status = "disabled"; 355 349 };
+55 -31
arch/arm/boot/dts/sun6i-a31.dtsi
··· 174 174 clock-output-names = "axi"; 175 175 }; 176 176 177 - ahb1_mux: ahb1_mux@01c20054 { 178 - #clock-cells = <0>; 179 - compatible = "allwinner,sun6i-a31-ahb1-mux-clk"; 180 - reg = <0x01c20054 0x4>; 181 - clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>; 182 - clock-output-names = "ahb1_mux"; 183 - }; 184 - 185 177 ahb1: ahb1@01c20054 { 186 178 #clock-cells = <0>; 187 - compatible = "allwinner,sun4i-a10-ahb-clk"; 179 + compatible = "allwinner,sun6i-a31-ahb1-clk"; 188 180 reg = <0x01c20054 0x4>; 189 - clocks = <&ahb1_mux>; 181 + clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>; 190 182 clock-output-names = "ahb1"; 191 183 }; 192 184 ··· 241 249 }; 242 250 243 251 mmc0_clk: clk@01c20088 { 244 - #clock-cells = <0>; 245 - compatible = "allwinner,sun4i-a10-mod0-clk"; 252 + #clock-cells = <1>; 253 + compatible = "allwinner,sun4i-a10-mmc-clk"; 246 254 reg = <0x01c20088 0x4>; 247 255 clocks = <&osc24M>, <&pll6 0>; 248 - clock-output-names = "mmc0"; 256 + clock-output-names = "mmc0", 257 + "mmc0_output", 258 + "mmc0_sample"; 249 259 }; 250 260 251 261 mmc1_clk: clk@01c2008c { 252 - #clock-cells = <0>; 253 - compatible = "allwinner,sun4i-a10-mod0-clk"; 262 + #clock-cells = <1>; 263 + compatible = "allwinner,sun4i-a10-mmc-clk"; 254 264 reg = <0x01c2008c 0x4>; 255 265 clocks = <&osc24M>, <&pll6 0>; 256 - clock-output-names = "mmc1"; 266 + clock-output-names = "mmc1", 267 + "mmc1_output", 268 + "mmc1_sample"; 257 269 }; 258 270 259 271 mmc2_clk: clk@01c20090 { 260 - #clock-cells = <0>; 261 - compatible = "allwinner,sun4i-a10-mod0-clk"; 272 + #clock-cells = <1>; 273 + compatible = "allwinner,sun4i-a10-mmc-clk"; 262 274 reg = <0x01c20090 0x4>; 263 275 clocks = <&osc24M>, <&pll6 0>; 264 - clock-output-names = "mmc2"; 276 + clock-output-names = "mmc2", 277 + "mmc2_output", 278 + "mmc2_sample"; 265 279 }; 266 280 267 281 mmc3_clk: clk@01c20094 { 268 - #clock-cells = <0>; 269 - compatible = "allwinner,sun4i-a10-mod0-clk"; 282 + #clock-cells = <1>; 283 + compatible = "allwinner,sun4i-a10-mmc-clk"; 270 284 reg = <0x01c20094 0x4>; 271 285 clocks = <&osc24M>, <&pll6 0>; 272 - clock-output-names = "mmc3"; 286 + clock-output-names = "mmc3", 287 + "mmc3_output", 288 + "mmc3_sample"; 273 289 }; 274 290 275 291 spi0_clk: clk@01c200a0 { ··· 367 367 #dma-cells = <1>; 368 368 369 369 /* DMA controller requires AHB1 clocked from PLL6 */ 370 - assigned-clocks = <&ahb1_mux>; 370 + assigned-clocks = <&ahb1>; 371 371 assigned-clock-parents = <&pll6 0>; 372 372 }; 373 373 374 374 mmc0: mmc@01c0f000 { 375 375 compatible = "allwinner,sun5i-a13-mmc"; 376 376 reg = <0x01c0f000 0x1000>; 377 - clocks = <&ahb1_gates 8>, <&mmc0_clk>; 378 - clock-names = "ahb", "mmc"; 377 + clocks = <&ahb1_gates 8>, 378 + <&mmc0_clk 0>, 379 + <&mmc0_clk 1>, 380 + <&mmc0_clk 2>; 381 + clock-names = "ahb", 382 + "mmc", 383 + "output", 384 + "sample"; 379 385 resets = <&ahb1_rst 8>; 380 386 reset-names = "ahb"; 381 387 interrupts = <0 60 4>; ··· 391 385 mmc1: mmc@01c10000 { 392 386 compatible = "allwinner,sun5i-a13-mmc"; 393 387 reg = <0x01c10000 0x1000>; 394 - clocks = <&ahb1_gates 9>, <&mmc1_clk>; 395 - clock-names = "ahb", "mmc"; 388 + clocks = <&ahb1_gates 9>, 389 + <&mmc1_clk 0>, 390 + <&mmc1_clk 1>, 391 + <&mmc1_clk 2>; 392 + clock-names = "ahb", 393 + "mmc", 394 + "output", 395 + "sample"; 396 396 resets = <&ahb1_rst 9>; 397 397 reset-names = "ahb"; 398 398 interrupts = <0 61 4>; ··· 408 396 mmc2: mmc@01c11000 { 409 397 compatible = "allwinner,sun5i-a13-mmc"; 410 398 reg = <0x01c11000 0x1000>; 411 - clocks = <&ahb1_gates 10>, <&mmc2_clk>; 412 - clock-names = "ahb", "mmc"; 399 + clocks = <&ahb1_gates 10>, 400 + <&mmc2_clk 0>, 401 + <&mmc2_clk 1>, 402 + <&mmc2_clk 2>; 403 + clock-names = "ahb", 404 + "mmc", 405 + "output", 406 + "sample"; 413 407 resets = <&ahb1_rst 10>; 414 408 reset-names = "ahb"; 415 409 interrupts = <0 62 4>; ··· 425 407 mmc3: mmc@01c12000 { 426 408 compatible = "allwinner,sun5i-a13-mmc"; 427 409 reg = <0x01c12000 0x1000>; 428 - clocks = <&ahb1_gates 11>, <&mmc3_clk>; 429 - clock-names = "ahb", "mmc"; 410 + clocks = <&ahb1_gates 11>, 411 + <&mmc3_clk 0>, 412 + <&mmc3_clk 1>, 413 + <&mmc3_clk 2>; 414 + clock-names = "ahb", 415 + "mmc", 416 + "output", 417 + "sample"; 430 418 resets = <&ahb1_rst 11>; 431 419 reset-names = "ahb"; 432 420 interrupts = <0 63 4>;
+52 -20
arch/arm/boot/dts/sun7i-a20.dtsi
··· 274 274 }; 275 275 276 276 mmc0_clk: clk@01c20088 { 277 - #clock-cells = <0>; 278 - compatible = "allwinner,sun4i-a10-mod0-clk"; 277 + #clock-cells = <1>; 278 + compatible = "allwinner,sun4i-a10-mmc-clk"; 279 279 reg = <0x01c20088 0x4>; 280 280 clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; 281 - clock-output-names = "mmc0"; 281 + clock-output-names = "mmc0", 282 + "mmc0_output", 283 + "mmc0_sample"; 282 284 }; 283 285 284 286 mmc1_clk: clk@01c2008c { 285 - #clock-cells = <0>; 286 - compatible = "allwinner,sun4i-a10-mod0-clk"; 287 + #clock-cells = <1>; 288 + compatible = "allwinner,sun4i-a10-mmc-clk"; 287 289 reg = <0x01c2008c 0x4>; 288 290 clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; 289 - clock-output-names = "mmc1"; 291 + clock-output-names = "mmc1", 292 + "mmc1_output", 293 + "mmc1_sample"; 290 294 }; 291 295 292 296 mmc2_clk: clk@01c20090 { 293 - #clock-cells = <0>; 294 - compatible = "allwinner,sun4i-a10-mod0-clk"; 297 + #clock-cells = <1>; 298 + compatible = "allwinner,sun4i-a10-mmc-clk"; 295 299 reg = <0x01c20090 0x4>; 296 300 clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; 297 - clock-output-names = "mmc2"; 301 + clock-output-names = "mmc2", 302 + "mmc2_output", 303 + "mmc2_sample"; 298 304 }; 299 305 300 306 mmc3_clk: clk@01c20094 { 301 - #clock-cells = <0>; 302 - compatible = "allwinner,sun4i-a10-mod0-clk"; 307 + #clock-cells = <1>; 308 + compatible = "allwinner,sun4i-a10-mmc-clk"; 303 309 reg = <0x01c20094 0x4>; 304 310 clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; 305 - clock-output-names = "mmc3"; 311 + clock-output-names = "mmc3", 312 + "mmc3_output", 313 + "mmc3_sample"; 306 314 }; 307 315 308 316 ts_clk: clk@01c20098 { ··· 526 518 mmc0: mmc@01c0f000 { 527 519 compatible = "allwinner,sun5i-a13-mmc"; 528 520 reg = <0x01c0f000 0x1000>; 529 - clocks = <&ahb_gates 8>, <&mmc0_clk>; 530 - clock-names = "ahb", "mmc"; 521 + clocks = <&ahb_gates 8>, 522 + <&mmc0_clk 0>, 523 + <&mmc0_clk 1>, 524 + <&mmc0_clk 2>; 525 + clock-names = "ahb", 526 + "mmc", 527 + "output", 528 + "sample"; 531 529 interrupts = <0 32 4>; 532 530 status = "disabled"; 533 531 }; ··· 541 527 mmc1: mmc@01c10000 { 542 528 compatible = "allwinner,sun5i-a13-mmc"; 543 529 reg = <0x01c10000 0x1000>; 544 - clocks = <&ahb_gates 9>, <&mmc1_clk>; 545 - clock-names = "ahb", "mmc"; 530 + clocks = <&ahb_gates 9>, 531 + <&mmc1_clk 0>, 532 + <&mmc1_clk 1>, 533 + <&mmc1_clk 2>; 534 + clock-names = "ahb", 535 + "mmc", 536 + "output", 537 + "sample"; 546 538 interrupts = <0 33 4>; 547 539 status = "disabled"; 548 540 }; ··· 556 536 mmc2: mmc@01c11000 { 557 537 compatible = "allwinner,sun5i-a13-mmc"; 558 538 reg = <0x01c11000 0x1000>; 559 - clocks = <&ahb_gates 10>, <&mmc2_clk>; 560 - clock-names = "ahb", "mmc"; 539 + clocks = <&ahb_gates 10>, 540 + <&mmc2_clk 0>, 541 + <&mmc2_clk 1>, 542 + <&mmc2_clk 2>; 543 + clock-names = "ahb", 544 + "mmc", 545 + "output", 546 + "sample"; 561 547 interrupts = <0 34 4>; 562 548 status = "disabled"; 563 549 }; ··· 571 545 mmc3: mmc@01c12000 { 572 546 compatible = "allwinner,sun5i-a13-mmc"; 573 547 reg = <0x01c12000 0x1000>; 574 - clocks = <&ahb_gates 11>, <&mmc3_clk>; 575 - clock-names = "ahb", "mmc"; 548 + clocks = <&ahb_gates 11>, 549 + <&mmc3_clk 0>, 550 + <&mmc3_clk 1>, 551 + <&mmc3_clk 2>; 552 + clock-names = "ahb", 553 + "mmc", 554 + "output", 555 + "sample"; 576 556 interrupts = <0 35 4>; 577 557 status = "disabled"; 578 558 };
+64 -32
arch/arm/boot/dts/sun8i-a23.dtsi
··· 110 110 }; 111 111 112 112 /* dummy clock until actually implemented */ 113 - pll6: pll6_clk { 113 + pll5: pll5_clk { 114 114 #clock-cells = <0>; 115 115 compatible = "fixed-clock"; 116 - clock-frequency = <600000000>; 117 - clock-output-names = "pll6"; 116 + clock-frequency = <0>; 117 + clock-output-names = "pll5"; 118 + }; 119 + 120 + pll6: clk@01c20028 { 121 + #clock-cells = <1>; 122 + compatible = "allwinner,sun6i-a31-pll6-clk"; 123 + reg = <0x01c20028 0x4>; 124 + clocks = <&osc24M>; 125 + clock-output-names = "pll6", "pll6x2"; 118 126 }; 119 127 120 128 cpu: cpu_clk@01c20050 { ··· 148 140 clock-output-names = "axi"; 149 141 }; 150 142 151 - ahb1_mux: ahb1_mux_clk@01c20054 { 152 - #clock-cells = <0>; 153 - compatible = "allwinner,sun6i-a31-ahb1-mux-clk"; 154 - reg = <0x01c20054 0x4>; 155 - clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6>; 156 - clock-output-names = "ahb1_mux"; 157 - }; 158 - 159 143 ahb1: ahb1_clk@01c20054 { 160 144 #clock-cells = <0>; 161 - compatible = "allwinner,sun4i-a10-ahb-clk"; 145 + compatible = "allwinner,sun6i-a31-ahb1-clk"; 162 146 reg = <0x01c20054 0x4>; 163 - clocks = <&ahb1_mux>; 147 + clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>; 164 148 clock-output-names = "ahb1"; 165 149 }; 166 150 ··· 193 193 #clock-cells = <0>; 194 194 compatible = "allwinner,sun4i-a10-apb1-clk"; 195 195 reg = <0x01c20058 0x4>; 196 - clocks = <&osc32k>, <&osc24M>, <&pll6>, <&pll6>; 196 + clocks = <&osc32k>, <&osc24M>, <&pll6 0>, <&pll6 0>; 197 197 clock-output-names = "apb2"; 198 198 }; 199 199 ··· 209 209 }; 210 210 211 211 mmc0_clk: clk@01c20088 { 212 - #clock-cells = <0>; 213 - compatible = "allwinner,sun4i-a10-mod0-clk"; 212 + #clock-cells = <1>; 213 + compatible = "allwinner,sun4i-a10-mmc-clk"; 214 214 reg = <0x01c20088 0x4>; 215 - clocks = <&osc24M>, <&pll6>; 216 - clock-output-names = "mmc0"; 215 + clocks = <&osc24M>, <&pll6 0>; 216 + clock-output-names = "mmc0", 217 + "mmc0_output", 218 + "mmc0_sample"; 217 219 }; 218 220 219 221 mmc1_clk: clk@01c2008c { 220 - #clock-cells = <0>; 221 - compatible = "allwinner,sun4i-a10-mod0-clk"; 222 + #clock-cells = <1>; 223 + compatible = "allwinner,sun4i-a10-mmc-clk"; 222 224 reg = <0x01c2008c 0x4>; 223 - clocks = <&osc24M>, <&pll6>; 224 - clock-output-names = "mmc1"; 225 + clocks = <&osc24M>, <&pll6 0>; 226 + clock-output-names = "mmc1", 227 + "mmc1_output", 228 + "mmc1_sample"; 225 229 }; 226 230 227 231 mmc2_clk: clk@01c20090 { 228 - #clock-cells = <0>; 229 - compatible = "allwinner,sun4i-a10-mod0-clk"; 232 + #clock-cells = <1>; 233 + compatible = "allwinner,sun4i-a10-mmc-clk"; 230 234 reg = <0x01c20090 0x4>; 231 - clocks = <&osc24M>, <&pll6>; 232 - clock-output-names = "mmc2"; 235 + clocks = <&osc24M>, <&pll6 0>; 236 + clock-output-names = "mmc2", 237 + "mmc2_output", 238 + "mmc2_sample"; 239 + }; 240 + 241 + mbus_clk: clk@01c2015c { 242 + #clock-cells = <0>; 243 + compatible = "allwinner,sun8i-a23-mbus-clk"; 244 + reg = <0x01c2015c 0x4>; 245 + clocks = <&osc24M>, <&pll6 1>, <&pll5>; 246 + clock-output-names = "mbus"; 233 247 }; 234 248 }; 235 249 ··· 265 251 mmc0: mmc@01c0f000 { 266 252 compatible = "allwinner,sun5i-a13-mmc"; 267 253 reg = <0x01c0f000 0x1000>; 268 - clocks = <&ahb1_gates 8>, <&mmc0_clk>; 269 - clock-names = "ahb", "mmc"; 254 + clocks = <&ahb1_gates 8>, 255 + <&mmc0_clk 0>, 256 + <&mmc0_clk 1>, 257 + <&mmc0_clk 2>; 258 + clock-names = "ahb", 259 + "mmc", 260 + "output", 261 + "sample"; 270 262 resets = <&ahb1_rst 8>; 271 263 reset-names = "ahb"; 272 264 interrupts = <0 60 4>; ··· 282 262 mmc1: mmc@01c10000 { 283 263 compatible = "allwinner,sun5i-a13-mmc"; 284 264 reg = <0x01c10000 0x1000>; 285 - clocks = <&ahb1_gates 9>, <&mmc1_clk>; 286 - clock-names = "ahb", "mmc"; 265 + clocks = <&ahb1_gates 9>, 266 + <&mmc1_clk 0>, 267 + <&mmc1_clk 1>, 268 + <&mmc1_clk 2>; 269 + clock-names = "ahb", 270 + "mmc", 271 + "output", 272 + "sample"; 287 273 resets = <&ahb1_rst 9>; 288 274 reset-names = "ahb"; 289 275 interrupts = <0 61 4>; ··· 299 273 mmc2: mmc@01c11000 { 300 274 compatible = "allwinner,sun5i-a13-mmc"; 301 275 reg = <0x01c11000 0x1000>; 302 - clocks = <&ahb1_gates 10>, <&mmc2_clk>; 303 - clock-names = "ahb", "mmc"; 276 + clocks = <&ahb1_gates 10>, 277 + <&mmc2_clk 0>, 278 + <&mmc2_clk 1>, 279 + <&mmc2_clk 2>; 280 + clock-names = "ahb", 281 + "mmc", 282 + "output", 283 + "sample"; 304 284 resets = <&ahb1_rst 10>; 305 285 reset-names = "ahb"; 306 286 interrupts = <0 62 4>;
+1
drivers/clk/sunxi/Makefile
··· 8 8 obj-y += clk-mod0.o 9 9 obj-y += clk-sun8i-mbus.o 10 10 obj-y += clk-sun9i-core.o 11 + obj-y += clk-sun9i-mmc.o 11 12 12 13 obj-$(CONFIG_MFD_SUN6I_PRCM) += \ 13 14 clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
+4 -6
drivers/clk/sunxi/clk-factors.c
··· 156 156 .set_rate = clk_factors_set_rate, 157 157 }; 158 158 159 - struct clk * __init sunxi_factors_register(struct device_node *node, 160 - const struct factors_data *data, 161 - spinlock_t *lock) 159 + struct clk *sunxi_factors_register(struct device_node *node, 160 + const struct factors_data *data, 161 + spinlock_t *lock, 162 + void __iomem *reg) 162 163 { 163 164 struct clk *clk; 164 165 struct clk_factors *factors; ··· 169 168 struct clk_hw *mux_hw = NULL; 170 169 const char *clk_name = node->name; 171 170 const char *parents[FACTORS_MAX_PARENTS]; 172 - void __iomem *reg; 173 171 int i = 0; 174 - 175 - reg = of_iomap(node, 0); 176 172 177 173 /* if we have a mux, we will have >1 parents */ 178 174 while (i < FACTORS_MAX_PARENTS &&
+4 -3
drivers/clk/sunxi/clk-factors.h
··· 36 36 spinlock_t *lock; 37 37 }; 38 38 39 - struct clk * __init sunxi_factors_register(struct device_node *node, 40 - const struct factors_data *data, 41 - spinlock_t *lock); 39 + struct clk *sunxi_factors_register(struct device_node *node, 40 + const struct factors_data *data, 41 + spinlock_t *lock, 42 + void __iomem *reg); 42 43 43 44 #endif
+161 -53
drivers/clk/sunxi/clk-mod0.c
··· 17 17 #include <linux/clk-provider.h> 18 18 #include <linux/clkdev.h> 19 19 #include <linux/of_address.h> 20 + #include <linux/platform_device.h> 20 21 21 22 #include "clk-factors.h" 22 23 ··· 68 67 .pwidth = 2, 69 68 }; 70 69 71 - static const struct factors_data sun4i_a10_mod0_data __initconst = { 70 + static const struct factors_data sun4i_a10_mod0_data = { 72 71 .enable = 31, 73 72 .mux = 24, 74 73 .muxmask = BIT(1) | BIT(0), ··· 80 79 81 80 static void __init sun4i_a10_mod0_setup(struct device_node *node) 82 81 { 83 - sunxi_factors_register(node, &sun4i_a10_mod0_data, &sun4i_a10_mod0_lock); 82 + void __iomem *reg; 83 + 84 + reg = of_iomap(node, 0); 85 + if (!reg) { 86 + /* 87 + * This happens with mod0 clk nodes instantiated through 88 + * mfd, as those do not have their resources assigned at 89 + * CLK_OF_DECLARE time yet, so do not print an error. 90 + */ 91 + return; 92 + } 93 + 94 + sunxi_factors_register(node, &sun4i_a10_mod0_data, 95 + &sun4i_a10_mod0_lock, reg); 84 96 } 85 97 CLK_OF_DECLARE(sun4i_a10_mod0, "allwinner,sun4i-a10-mod0-clk", sun4i_a10_mod0_setup); 98 + 99 + static int sun4i_a10_mod0_clk_probe(struct platform_device *pdev) 100 + { 101 + struct device_node *np = pdev->dev.of_node; 102 + struct resource *r; 103 + void __iomem *reg; 104 + 105 + if (!np) 106 + return -ENODEV; 107 + 108 + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 109 + reg = devm_ioremap_resource(&pdev->dev, r); 110 + if (IS_ERR(reg)) 111 + return PTR_ERR(reg); 112 + 113 + sunxi_factors_register(np, &sun4i_a10_mod0_data, 114 + &sun4i_a10_mod0_lock, reg); 115 + return 0; 116 + } 117 + 118 + static const struct of_device_id sun4i_a10_mod0_clk_dt_ids[] = { 119 + { .compatible = "allwinner,sun4i-a10-mod0-clk" }, 120 + { /* sentinel */ } 121 + }; 122 + 123 + static struct platform_driver sun4i_a10_mod0_clk_driver = { 124 + .driver = { 125 + .name = "sun4i-a10-mod0-clk", 126 + .of_match_table = sun4i_a10_mod0_clk_dt_ids, 127 + }, 128 + .probe = sun4i_a10_mod0_clk_probe, 129 + }; 130 + module_platform_driver(sun4i_a10_mod0_clk_driver); 131 + 132 + static const struct factors_data sun9i_a80_mod0_data __initconst = { 133 + .enable = 31, 134 + .mux = 24, 135 + .muxmask = BIT(3) | BIT(2) | BIT(1) | BIT(0), 136 + .table = &sun4i_a10_mod0_config, 137 + .getter = sun4i_a10_get_mod0_factors, 138 + }; 139 + 140 + static void __init sun9i_a80_mod0_setup(struct device_node *node) 141 + { 142 + void __iomem *reg; 143 + 144 + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 145 + if (IS_ERR(reg)) { 146 + pr_err("Could not get registers for mod0-clk: %s\n", 147 + node->name); 148 + return; 149 + } 150 + 151 + sunxi_factors_register(node, &sun9i_a80_mod0_data, 152 + &sun4i_a10_mod0_lock, reg); 153 + } 154 + CLK_OF_DECLARE(sun9i_a80_mod0, "allwinner,sun9i-a80-mod0-clk", sun9i_a80_mod0_setup); 86 155 87 156 static DEFINE_SPINLOCK(sun5i_a13_mbus_lock); 88 157 89 158 static void __init sun5i_a13_mbus_setup(struct device_node *node) 90 159 { 91 - struct clk *mbus = sunxi_factors_register(node, &sun4i_a10_mod0_data, &sun5i_a13_mbus_lock); 160 + struct clk *mbus; 161 + void __iomem *reg; 162 + 163 + reg = of_iomap(node, 0); 164 + if (!reg) { 165 + pr_err("Could not get registers for a13-mbus-clk\n"); 166 + return; 167 + } 168 + 169 + mbus = sunxi_factors_register(node, &sun4i_a10_mod0_data, 170 + &sun5i_a13_mbus_lock, reg); 92 171 93 172 /* The MBUS clocks needs to be always enabled */ 94 173 __clk_get(mbus); ··· 176 95 } 177 96 CLK_OF_DECLARE(sun5i_a13_mbus, "allwinner,sun5i-a13-mbus-clk", sun5i_a13_mbus_setup); 178 97 179 - struct mmc_phase_data { 180 - u8 offset; 181 - }; 182 - 183 98 struct mmc_phase { 184 99 struct clk_hw hw; 100 + u8 offset; 185 101 void __iomem *reg; 186 - struct mmc_phase_data *data; 187 102 spinlock_t *lock; 188 103 }; 189 104 ··· 195 118 u8 delay; 196 119 197 120 value = readl(phase->reg); 198 - delay = (value >> phase->data->offset) & 0x3; 121 + delay = (value >> phase->offset) & 0x3; 199 122 200 123 if (!delay) 201 124 return 180; ··· 283 206 284 207 spin_lock_irqsave(phase->lock, flags); 285 208 value = readl(phase->reg); 286 - value &= ~GENMASK(phase->data->offset + 3, phase->data->offset); 287 - value |= delay << phase->data->offset; 209 + value &= ~GENMASK(phase->offset + 3, phase->offset); 210 + value |= delay << phase->offset; 288 211 writel(value, phase->reg); 289 212 spin_unlock_irqrestore(phase->lock, flags); 290 213 ··· 296 219 .set_phase = mmc_set_phase, 297 220 }; 298 221 299 - static void __init sun4i_a10_mmc_phase_setup(struct device_node *node, 300 - struct mmc_phase_data *data) 222 + /* 223 + * sunxi_mmc_setup - Common setup function for mmc module clocks 224 + * 225 + * The only difference between module clocks on different platforms is the 226 + * width of the mux register bits and the valid values, which are passed in 227 + * through struct factors_data. The phase clocks parts are identical. 228 + */ 229 + static void __init sunxi_mmc_setup(struct device_node *node, 230 + const struct factors_data *data, 231 + spinlock_t *lock) 301 232 { 302 - const char *parent_names[1] = { of_clk_get_parent_name(node, 0) }; 303 - struct clk_init_data init = { 304 - .num_parents = 1, 305 - .parent_names = parent_names, 306 - .ops = &mmc_clk_ops, 307 - }; 233 + struct clk_onecell_data *clk_data; 234 + const char *parent; 235 + void __iomem *reg; 236 + int i; 308 237 309 - struct mmc_phase *phase; 310 - struct clk *clk; 238 + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 239 + if (IS_ERR(reg)) { 240 + pr_err("Couldn't map the %s clock registers\n", node->name); 241 + return; 242 + } 311 243 312 - phase = kmalloc(sizeof(*phase), GFP_KERNEL); 313 - if (!phase) 244 + clk_data = kmalloc(sizeof(*clk_data), GFP_KERNEL); 245 + if (!clk_data) 314 246 return; 315 247 316 - phase->hw.init = &init; 248 + clk_data->clks = kcalloc(3, sizeof(*clk_data->clks), GFP_KERNEL); 249 + if (!clk_data->clks) 250 + goto err_free_data; 317 251 318 - phase->reg = of_iomap(node, 0); 319 - if (!phase->reg) 320 - goto err_free; 252 + clk_data->clk_num = 3; 253 + clk_data->clks[0] = sunxi_factors_register(node, data, lock, reg); 254 + if (!clk_data->clks[0]) 255 + goto err_free_clks; 321 256 322 - phase->data = data; 323 - phase->lock = &sun4i_a10_mod0_lock; 257 + parent = __clk_get_name(clk_data->clks[0]); 324 258 325 - if (of_property_read_string(node, "clock-output-names", &init.name)) 326 - init.name = node->name; 259 + for (i = 1; i < 3; i++) { 260 + struct clk_init_data init = { 261 + .num_parents = 1, 262 + .parent_names = &parent, 263 + .ops = &mmc_clk_ops, 264 + }; 265 + struct mmc_phase *phase; 327 266 328 - clk = clk_register(NULL, &phase->hw); 329 - if (IS_ERR(clk)) 330 - goto err_unmap; 267 + phase = kmalloc(sizeof(*phase), GFP_KERNEL); 268 + if (!phase) 269 + continue; 331 270 332 - of_clk_add_provider(node, of_clk_src_simple_get, clk); 271 + phase->hw.init = &init; 272 + phase->reg = reg; 273 + phase->lock = lock; 274 + 275 + if (i == 1) 276 + phase->offset = 8; 277 + else 278 + phase->offset = 20; 279 + 280 + if (of_property_read_string_index(node, "clock-output-names", 281 + i, &init.name)) 282 + init.name = node->name; 283 + 284 + clk_data->clks[i] = clk_register(NULL, &phase->hw); 285 + if (IS_ERR(clk_data->clks[i])) { 286 + kfree(phase); 287 + continue; 288 + } 289 + } 290 + 291 + of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); 333 292 334 293 return; 335 294 336 - err_unmap: 337 - iounmap(phase->reg); 338 - err_free: 339 - kfree(phase); 295 + err_free_clks: 296 + kfree(clk_data->clks); 297 + err_free_data: 298 + kfree(clk_data); 340 299 } 341 300 301 + static DEFINE_SPINLOCK(sun4i_a10_mmc_lock); 342 302 343 - static struct mmc_phase_data mmc_output_clk = { 344 - .offset = 8, 345 - }; 346 - 347 - static struct mmc_phase_data mmc_sample_clk = { 348 - .offset = 20, 349 - }; 350 - 351 - static void __init sun4i_a10_mmc_output_setup(struct device_node *node) 303 + static void __init sun4i_a10_mmc_setup(struct device_node *node) 352 304 { 353 - sun4i_a10_mmc_phase_setup(node, &mmc_output_clk); 305 + sunxi_mmc_setup(node, &sun4i_a10_mod0_data, &sun4i_a10_mmc_lock); 354 306 } 355 - CLK_OF_DECLARE(sun4i_a10_mmc_output, "allwinner,sun4i-a10-mmc-output-clk", sun4i_a10_mmc_output_setup); 307 + CLK_OF_DECLARE(sun4i_a10_mmc, "allwinner,sun4i-a10-mmc-clk", sun4i_a10_mmc_setup); 356 308 357 - static void __init sun4i_a10_mmc_sample_setup(struct device_node *node) 309 + static DEFINE_SPINLOCK(sun9i_a80_mmc_lock); 310 + 311 + static void __init sun9i_a80_mmc_setup(struct device_node *node) 358 312 { 359 - sun4i_a10_mmc_phase_setup(node, &mmc_sample_clk); 313 + sunxi_mmc_setup(node, &sun9i_a80_mod0_data, &sun9i_a80_mmc_lock); 360 314 } 361 - CLK_OF_DECLARE(sun4i_a10_mmc_sample, "allwinner,sun4i-a10-mmc-sample-clk", sun4i_a10_mmc_sample_setup); 315 + CLK_OF_DECLARE(sun9i_a80_mmc, "allwinner,sun9i-a80-mmc-clk", sun9i_a80_mmc_setup);
+11 -2
drivers/clk/sunxi/clk-sun8i-mbus.c
··· 69 69 70 70 static void __init sun8i_a23_mbus_setup(struct device_node *node) 71 71 { 72 - struct clk *mbus = sunxi_factors_register(node, &sun8i_a23_mbus_data, 73 - &sun8i_a23_mbus_lock); 72 + struct clk *mbus; 73 + void __iomem *reg; 74 + 75 + reg = of_iomap(node, 0); 76 + if (!reg) { 77 + pr_err("Could not get registers for a23-mbus-clk\n"); 78 + return; 79 + } 80 + 81 + mbus = sunxi_factors_register(node, &sun8i_a23_mbus_data, 82 + &sun8i_a23_mbus_lock, reg); 74 83 75 84 /* The MBUS clocks needs to be always enabled */ 76 85 __clk_get(mbus);
+85 -34
drivers/clk/sunxi/clk-sun9i-core.c
··· 24 24 25 25 26 26 /** 27 - * sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL1 27 + * sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL4 28 28 * PLL4 rate is calculated as follows 29 29 * rate = (parent_rate * n >> p) / (m + 1); 30 - * parent_rate is always 24Mhz 30 + * parent_rate is always 24MHz 31 31 * 32 32 * p and m are named div1 and div2 in Allwinner's SDK 33 33 */ 34 34 35 35 static void sun9i_a80_get_pll4_factors(u32 *freq, u32 parent_rate, 36 - u8 *n, u8 *k, u8 *m, u8 *p) 36 + u8 *n_ret, u8 *k, u8 *m_ret, u8 *p_ret) 37 37 { 38 - int div; 38 + int n; 39 + int m = 1; 40 + int p = 1; 39 41 40 - /* Normalize value to a 6M multiple */ 41 - div = DIV_ROUND_UP(*freq, 6000000); 42 + /* Normalize value to a 6 MHz multiple (24 MHz / 4) */ 43 + n = DIV_ROUND_UP(*freq, 6000000); 42 44 43 - /* divs above 256 cannot be odd */ 44 - if (div > 256) 45 - div = round_up(div, 2); 45 + /* If n is too large switch to steps of 12 MHz */ 46 + if (n > 255) { 47 + m = 0; 48 + n = (n + 1) / 2; 49 + } 46 50 47 - /* divs above 512 must be a multiple of 4 */ 48 - if (div > 512) 49 - div = round_up(div, 4); 51 + /* If n is still too large switch to steps of 24 MHz */ 52 + if (n > 255) { 53 + p = 0; 54 + n = (n + 1) / 2; 55 + } 50 56 51 - *freq = 6000000 * div; 57 + /* n must be between 12 and 255 */ 58 + if (n > 255) 59 + n = 255; 60 + else if (n < 12) 61 + n = 12; 62 + 63 + *freq = ((24000000 * n) >> p) / (m + 1); 52 64 53 65 /* we were called to round the frequency, we can now return */ 54 - if (n == NULL) 66 + if (n_ret == NULL) 55 67 return; 56 68 57 - /* p will be 1 for divs under 512 */ 58 - if (div < 512) 59 - *p = 1; 60 - else 61 - *p = 0; 62 - 63 - /* m will be 1 if div is odd */ 64 - if (div & 1) 65 - *m = 1; 66 - else 67 - *m = 0; 68 - 69 - /* calculate a suitable n based on m and p */ 70 - *n = div / (*p + 1) / (*m + 1); 69 + *n_ret = n; 70 + *m_ret = m; 71 + *p_ret = p; 71 72 } 72 73 73 74 static struct clk_factors_config sun9i_a80_pll4_config = { ··· 90 89 91 90 static void __init sun9i_a80_pll4_setup(struct device_node *node) 92 91 { 93 - sunxi_factors_register(node, &sun9i_a80_pll4_data, &sun9i_a80_pll4_lock); 92 + void __iomem *reg; 93 + 94 + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 95 + if (!reg) { 96 + pr_err("Could not get registers for a80-pll4-clk: %s\n", 97 + node->name); 98 + return; 99 + } 100 + 101 + sunxi_factors_register(node, &sun9i_a80_pll4_data, 102 + &sun9i_a80_pll4_lock, reg); 94 103 } 95 104 CLK_OF_DECLARE(sun9i_a80_pll4, "allwinner,sun9i-a80-pll4-clk", sun9i_a80_pll4_setup); 96 105 ··· 150 139 151 140 static void __init sun9i_a80_gt_setup(struct device_node *node) 152 141 { 153 - struct clk *gt = sunxi_factors_register(node, &sun9i_a80_gt_data, 154 - &sun9i_a80_gt_lock); 142 + void __iomem *reg; 143 + struct clk *gt; 144 + 145 + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 146 + if (!reg) { 147 + pr_err("Could not get registers for a80-gt-clk: %s\n", 148 + node->name); 149 + return; 150 + } 151 + 152 + gt = sunxi_factors_register(node, &sun9i_a80_gt_data, 153 + &sun9i_a80_gt_lock, reg); 155 154 156 155 /* The GT bus clock needs to be always enabled */ 157 156 __clk_get(gt); ··· 215 194 216 195 static void __init sun9i_a80_ahb_setup(struct device_node *node) 217 196 { 218 - sunxi_factors_register(node, &sun9i_a80_ahb_data, &sun9i_a80_ahb_lock); 197 + void __iomem *reg; 198 + 199 + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 200 + if (!reg) { 201 + pr_err("Could not get registers for a80-ahb-clk: %s\n", 202 + node->name); 203 + return; 204 + } 205 + 206 + sunxi_factors_register(node, &sun9i_a80_ahb_data, 207 + &sun9i_a80_ahb_lock, reg); 219 208 } 220 209 CLK_OF_DECLARE(sun9i_a80_ahb, "allwinner,sun9i-a80-ahb-clk", sun9i_a80_ahb_setup); 221 210 ··· 241 210 242 211 static void __init sun9i_a80_apb0_setup(struct device_node *node) 243 212 { 244 - sunxi_factors_register(node, &sun9i_a80_apb0_data, &sun9i_a80_apb0_lock); 213 + void __iomem *reg; 214 + 215 + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 216 + if (!reg) { 217 + pr_err("Could not get registers for a80-apb0-clk: %s\n", 218 + node->name); 219 + return; 220 + } 221 + 222 + sunxi_factors_register(node, &sun9i_a80_apb0_data, 223 + &sun9i_a80_apb0_lock, reg); 245 224 } 246 225 CLK_OF_DECLARE(sun9i_a80_apb0, "allwinner,sun9i-a80-apb0-clk", sun9i_a80_apb0_setup); 247 226 ··· 307 266 308 267 static void __init sun9i_a80_apb1_setup(struct device_node *node) 309 268 { 310 - sunxi_factors_register(node, &sun9i_a80_apb1_data, &sun9i_a80_apb1_lock); 269 + void __iomem *reg; 270 + 271 + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 272 + if (!reg) { 273 + pr_err("Could not get registers for a80-apb1-clk: %s\n", 274 + node->name); 275 + return; 276 + } 277 + 278 + sunxi_factors_register(node, &sun9i_a80_apb1_data, 279 + &sun9i_a80_apb1_lock, reg); 311 280 } 312 281 CLK_OF_DECLARE(sun9i_a80_apb1, "allwinner,sun9i-a80-apb1-clk", sun9i_a80_apb1_setup);
+219
drivers/clk/sunxi/clk-sun9i-mmc.c
··· 1 + /* 2 + * Copyright 2015 Chen-Yu Tsai 3 + * 4 + * Chen-Yu Tsai <wens@csie.org> 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License, or 9 + * (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + */ 16 + 17 + #include <linux/clk-provider.h> 18 + #include <linux/clkdev.h> 19 + #include <linux/module.h> 20 + #include <linux/of.h> 21 + #include <linux/of_device.h> 22 + #include <linux/reset.h> 23 + #include <linux/platform_device.h> 24 + #include <linux/reset-controller.h> 25 + #include <linux/spinlock.h> 26 + 27 + #define SUN9I_MMC_WIDTH 4 28 + 29 + #define SUN9I_MMC_GATE_BIT 16 30 + #define SUN9I_MMC_RESET_BIT 18 31 + 32 + struct sun9i_mmc_clk_data { 33 + spinlock_t lock; 34 + void __iomem *membase; 35 + struct clk *clk; 36 + struct reset_control *reset; 37 + struct clk_onecell_data clk_data; 38 + struct reset_controller_dev rcdev; 39 + }; 40 + 41 + static int sun9i_mmc_reset_assert(struct reset_controller_dev *rcdev, 42 + unsigned long id) 43 + { 44 + struct sun9i_mmc_clk_data *data = container_of(rcdev, 45 + struct sun9i_mmc_clk_data, 46 + rcdev); 47 + unsigned long flags; 48 + void __iomem *reg = data->membase + SUN9I_MMC_WIDTH * id; 49 + u32 val; 50 + 51 + clk_prepare_enable(data->clk); 52 + spin_lock_irqsave(&data->lock, flags); 53 + 54 + val = readl(reg); 55 + writel(val & ~BIT(SUN9I_MMC_RESET_BIT), reg); 56 + 57 + spin_unlock_irqrestore(&data->lock, flags); 58 + clk_disable_unprepare(data->clk); 59 + 60 + return 0; 61 + } 62 + 63 + static int sun9i_mmc_reset_deassert(struct reset_controller_dev *rcdev, 64 + unsigned long id) 65 + { 66 + struct sun9i_mmc_clk_data *data = container_of(rcdev, 67 + struct sun9i_mmc_clk_data, 68 + rcdev); 69 + unsigned long flags; 70 + void __iomem *reg = data->membase + SUN9I_MMC_WIDTH * id; 71 + u32 val; 72 + 73 + clk_prepare_enable(data->clk); 74 + spin_lock_irqsave(&data->lock, flags); 75 + 76 + val = readl(reg); 77 + writel(val | BIT(SUN9I_MMC_RESET_BIT), reg); 78 + 79 + spin_unlock_irqrestore(&data->lock, flags); 80 + clk_disable_unprepare(data->clk); 81 + 82 + return 0; 83 + } 84 + 85 + static struct reset_control_ops sun9i_mmc_reset_ops = { 86 + .assert = sun9i_mmc_reset_assert, 87 + .deassert = sun9i_mmc_reset_deassert, 88 + }; 89 + 90 + static int sun9i_a80_mmc_config_clk_probe(struct platform_device *pdev) 91 + { 92 + struct device_node *np = pdev->dev.of_node; 93 + struct sun9i_mmc_clk_data *data; 94 + struct clk_onecell_data *clk_data; 95 + const char *clk_name = np->name; 96 + const char *clk_parent; 97 + struct resource *r; 98 + int count, i, ret; 99 + 100 + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 101 + if (!data) 102 + return -ENOMEM; 103 + 104 + spin_lock_init(&data->lock); 105 + 106 + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 107 + /* one clock/reset pair per word */ 108 + count = DIV_ROUND_UP((r->end - r->start + 1), SUN9I_MMC_WIDTH); 109 + data->membase = devm_ioremap_resource(&pdev->dev, r); 110 + if (IS_ERR(data->membase)) 111 + return PTR_ERR(data->membase); 112 + 113 + clk_data = &data->clk_data; 114 + clk_data->clk_num = count; 115 + clk_data->clks = devm_kcalloc(&pdev->dev, count, sizeof(struct clk *), 116 + GFP_KERNEL); 117 + if (!clk_data->clks) 118 + return -ENOMEM; 119 + 120 + data->clk = devm_clk_get(&pdev->dev, NULL); 121 + if (IS_ERR(data->clk)) { 122 + dev_err(&pdev->dev, "Could not get clock\n"); 123 + return PTR_ERR(data->clk); 124 + } 125 + 126 + data->reset = devm_reset_control_get(&pdev->dev, NULL); 127 + if (IS_ERR(data->reset)) { 128 + dev_err(&pdev->dev, "Could not get reset control\n"); 129 + return PTR_ERR(data->reset); 130 + } 131 + 132 + ret = reset_control_deassert(data->reset); 133 + if (ret) { 134 + dev_err(&pdev->dev, "Reset deassert err %d\n", ret); 135 + return ret; 136 + } 137 + 138 + clk_parent = __clk_get_name(data->clk); 139 + for (i = 0; i < count; i++) { 140 + of_property_read_string_index(np, "clock-output-names", 141 + i, &clk_name); 142 + 143 + clk_data->clks[i] = clk_register_gate(&pdev->dev, clk_name, 144 + clk_parent, 0, 145 + data->membase + SUN9I_MMC_WIDTH * i, 146 + SUN9I_MMC_GATE_BIT, 0, 147 + &data->lock); 148 + 149 + if (IS_ERR(clk_data->clks[i])) { 150 + ret = PTR_ERR(clk_data->clks[i]); 151 + goto err_clk_register; 152 + } 153 + } 154 + 155 + ret = of_clk_add_provider(np, of_clk_src_onecell_get, clk_data); 156 + if (ret) 157 + goto err_clk_provider; 158 + 159 + data->rcdev.owner = THIS_MODULE; 160 + data->rcdev.nr_resets = count; 161 + data->rcdev.ops = &sun9i_mmc_reset_ops; 162 + data->rcdev.of_node = pdev->dev.of_node; 163 + 164 + ret = reset_controller_register(&data->rcdev); 165 + if (ret) 166 + goto err_rc_reg; 167 + 168 + platform_set_drvdata(pdev, data); 169 + 170 + return 0; 171 + 172 + err_rc_reg: 173 + of_clk_del_provider(np); 174 + 175 + err_clk_provider: 176 + for (i = 0; i < count; i++) 177 + clk_unregister(clk_data->clks[i]); 178 + 179 + err_clk_register: 180 + reset_control_assert(data->reset); 181 + 182 + return ret; 183 + } 184 + 185 + static int sun9i_a80_mmc_config_clk_remove(struct platform_device *pdev) 186 + { 187 + struct device_node *np = pdev->dev.of_node; 188 + struct sun9i_mmc_clk_data *data = platform_get_drvdata(pdev); 189 + struct clk_onecell_data *clk_data = &data->clk_data; 190 + int i; 191 + 192 + reset_controller_unregister(&data->rcdev); 193 + of_clk_del_provider(np); 194 + for (i = 0; i < clk_data->clk_num; i++) 195 + clk_unregister(clk_data->clks[i]); 196 + 197 + reset_control_assert(data->reset); 198 + 199 + return 0; 200 + } 201 + 202 + static const struct of_device_id sun9i_a80_mmc_config_clk_dt_ids[] = { 203 + { .compatible = "allwinner,sun9i-a80-mmc-config-clk" }, 204 + { /* sentinel */ } 205 + }; 206 + 207 + static struct platform_driver sun9i_a80_mmc_config_clk_driver = { 208 + .driver = { 209 + .name = "sun9i-a80-mmc-config-clk", 210 + .of_match_table = sun9i_a80_mmc_config_clk_dt_ids, 211 + }, 212 + .probe = sun9i_a80_mmc_config_clk_probe, 213 + .remove = sun9i_a80_mmc_config_clk_remove, 214 + }; 215 + module_platform_driver(sun9i_a80_mmc_config_clk_driver); 216 + 217 + MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>"); 218 + MODULE_DESCRIPTION("Allwinner A80 MMC clock/reset Driver"); 219 + MODULE_LICENSE("GPL v2");
+220 -40
drivers/clk/sunxi/clk-sunxi.c
··· 20 20 #include <linux/of_address.h> 21 21 #include <linux/reset-controller.h> 22 22 #include <linux/spinlock.h> 23 + #include <linux/log2.h> 23 24 24 25 #include "clk-factors.h" 25 26 26 27 static DEFINE_SPINLOCK(clk_lock); 28 + 29 + /** 30 + * sun6i_a31_ahb1_clk_setup() - Setup function for a31 ahb1 composite clk 31 + */ 32 + 33 + #define SUN6I_AHB1_MAX_PARENTS 4 34 + #define SUN6I_AHB1_MUX_PARENT_PLL6 3 35 + #define SUN6I_AHB1_MUX_SHIFT 12 36 + /* un-shifted mask is what mux_clk expects */ 37 + #define SUN6I_AHB1_MUX_MASK 0x3 38 + #define SUN6I_AHB1_MUX_GET_PARENT(reg) ((reg >> SUN6I_AHB1_MUX_SHIFT) & \ 39 + SUN6I_AHB1_MUX_MASK) 40 + 41 + #define SUN6I_AHB1_DIV_SHIFT 4 42 + #define SUN6I_AHB1_DIV_MASK (0x3 << SUN6I_AHB1_DIV_SHIFT) 43 + #define SUN6I_AHB1_DIV_GET(reg) ((reg & SUN6I_AHB1_DIV_MASK) >> \ 44 + SUN6I_AHB1_DIV_SHIFT) 45 + #define SUN6I_AHB1_DIV_SET(reg, div) ((reg & ~SUN6I_AHB1_DIV_MASK) | \ 46 + (div << SUN6I_AHB1_DIV_SHIFT)) 47 + #define SUN6I_AHB1_PLL6_DIV_SHIFT 6 48 + #define SUN6I_AHB1_PLL6_DIV_MASK (0x3 << SUN6I_AHB1_PLL6_DIV_SHIFT) 49 + #define SUN6I_AHB1_PLL6_DIV_GET(reg) ((reg & SUN6I_AHB1_PLL6_DIV_MASK) >> \ 50 + SUN6I_AHB1_PLL6_DIV_SHIFT) 51 + #define SUN6I_AHB1_PLL6_DIV_SET(reg, div) ((reg & ~SUN6I_AHB1_PLL6_DIV_MASK) | \ 52 + (div << SUN6I_AHB1_PLL6_DIV_SHIFT)) 53 + 54 + struct sun6i_ahb1_clk { 55 + struct clk_hw hw; 56 + void __iomem *reg; 57 + }; 58 + 59 + #define to_sun6i_ahb1_clk(_hw) container_of(_hw, struct sun6i_ahb1_clk, hw) 60 + 61 + static unsigned long sun6i_ahb1_clk_recalc_rate(struct clk_hw *hw, 62 + unsigned long parent_rate) 63 + { 64 + struct sun6i_ahb1_clk *ahb1 = to_sun6i_ahb1_clk(hw); 65 + unsigned long rate; 66 + u32 reg; 67 + 68 + /* Fetch the register value */ 69 + reg = readl(ahb1->reg); 70 + 71 + /* apply pre-divider first if parent is pll6 */ 72 + if (SUN6I_AHB1_MUX_GET_PARENT(reg) == SUN6I_AHB1_MUX_PARENT_PLL6) 73 + parent_rate /= SUN6I_AHB1_PLL6_DIV_GET(reg) + 1; 74 + 75 + /* clk divider */ 76 + rate = parent_rate >> SUN6I_AHB1_DIV_GET(reg); 77 + 78 + return rate; 79 + } 80 + 81 + static long sun6i_ahb1_clk_round(unsigned long rate, u8 *divp, u8 *pre_divp, 82 + u8 parent, unsigned long parent_rate) 83 + { 84 + u8 div, calcp, calcm = 1; 85 + 86 + /* 87 + * clock can only divide, so we will never be able to achieve 88 + * frequencies higher than the parent frequency 89 + */ 90 + if (parent_rate && rate > parent_rate) 91 + rate = parent_rate; 92 + 93 + div = DIV_ROUND_UP(parent_rate, rate); 94 + 95 + /* calculate pre-divider if parent is pll6 */ 96 + if (parent == SUN6I_AHB1_MUX_PARENT_PLL6) { 97 + if (div < 4) 98 + calcp = 0; 99 + else if (div / 2 < 4) 100 + calcp = 1; 101 + else if (div / 4 < 4) 102 + calcp = 2; 103 + else 104 + calcp = 3; 105 + 106 + calcm = DIV_ROUND_UP(div, 1 << calcp); 107 + } else { 108 + calcp = __roundup_pow_of_two(div); 109 + calcp = calcp > 3 ? 3 : calcp; 110 + } 111 + 112 + /* we were asked to pass back divider values */ 113 + if (divp) { 114 + *divp = calcp; 115 + *pre_divp = calcm - 1; 116 + } 117 + 118 + return (parent_rate / calcm) >> calcp; 119 + } 120 + 121 + static long sun6i_ahb1_clk_determine_rate(struct clk_hw *hw, unsigned long rate, 122 + unsigned long *best_parent_rate, 123 + struct clk_hw **best_parent_clk) 124 + { 125 + struct clk *clk = hw->clk, *parent, *best_parent = NULL; 126 + int i, num_parents; 127 + unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0; 128 + 129 + /* find the parent that can help provide the fastest rate <= rate */ 130 + num_parents = __clk_get_num_parents(clk); 131 + for (i = 0; i < num_parents; i++) { 132 + parent = clk_get_parent_by_index(clk, i); 133 + if (!parent) 134 + continue; 135 + if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT) 136 + parent_rate = __clk_round_rate(parent, rate); 137 + else 138 + parent_rate = __clk_get_rate(parent); 139 + 140 + child_rate = sun6i_ahb1_clk_round(rate, NULL, NULL, i, 141 + parent_rate); 142 + 143 + if (child_rate <= rate && child_rate > best_child_rate) { 144 + best_parent = parent; 145 + best = parent_rate; 146 + best_child_rate = child_rate; 147 + } 148 + } 149 + 150 + if (best_parent) 151 + *best_parent_clk = __clk_get_hw(best_parent); 152 + *best_parent_rate = best; 153 + 154 + return best_child_rate; 155 + } 156 + 157 + static int sun6i_ahb1_clk_set_rate(struct clk_hw *hw, unsigned long rate, 158 + unsigned long parent_rate) 159 + { 160 + struct sun6i_ahb1_clk *ahb1 = to_sun6i_ahb1_clk(hw); 161 + unsigned long flags; 162 + u8 div, pre_div, parent; 163 + u32 reg; 164 + 165 + spin_lock_irqsave(&clk_lock, flags); 166 + 167 + reg = readl(ahb1->reg); 168 + 169 + /* need to know which parent is used to apply pre-divider */ 170 + parent = SUN6I_AHB1_MUX_GET_PARENT(reg); 171 + sun6i_ahb1_clk_round(rate, &div, &pre_div, parent, parent_rate); 172 + 173 + reg = SUN6I_AHB1_DIV_SET(reg, div); 174 + reg = SUN6I_AHB1_PLL6_DIV_SET(reg, pre_div); 175 + writel(reg, ahb1->reg); 176 + 177 + spin_unlock_irqrestore(&clk_lock, flags); 178 + 179 + return 0; 180 + } 181 + 182 + static const struct clk_ops sun6i_ahb1_clk_ops = { 183 + .determine_rate = sun6i_ahb1_clk_determine_rate, 184 + .recalc_rate = sun6i_ahb1_clk_recalc_rate, 185 + .set_rate = sun6i_ahb1_clk_set_rate, 186 + }; 187 + 188 + static void __init sun6i_ahb1_clk_setup(struct device_node *node) 189 + { 190 + struct clk *clk; 191 + struct sun6i_ahb1_clk *ahb1; 192 + struct clk_mux *mux; 193 + const char *clk_name = node->name; 194 + const char *parents[SUN6I_AHB1_MAX_PARENTS]; 195 + void __iomem *reg; 196 + int i = 0; 197 + 198 + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 199 + 200 + /* we have a mux, we will have >1 parents */ 201 + while (i < SUN6I_AHB1_MAX_PARENTS && 202 + (parents[i] = of_clk_get_parent_name(node, i)) != NULL) 203 + i++; 204 + 205 + of_property_read_string(node, "clock-output-names", &clk_name); 206 + 207 + ahb1 = kzalloc(sizeof(struct sun6i_ahb1_clk), GFP_KERNEL); 208 + if (!ahb1) 209 + return; 210 + 211 + mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); 212 + if (!mux) { 213 + kfree(ahb1); 214 + return; 215 + } 216 + 217 + /* set up clock properties */ 218 + mux->reg = reg; 219 + mux->shift = SUN6I_AHB1_MUX_SHIFT; 220 + mux->mask = SUN6I_AHB1_MUX_MASK; 221 + mux->lock = &clk_lock; 222 + ahb1->reg = reg; 223 + 224 + clk = clk_register_composite(NULL, clk_name, parents, i, 225 + &mux->hw, &clk_mux_ops, 226 + &ahb1->hw, &sun6i_ahb1_clk_ops, 227 + NULL, NULL, 0); 228 + 229 + if (!IS_ERR(clk)) { 230 + of_clk_add_provider(node, of_clk_src_simple_get, clk); 231 + clk_register_clkdev(clk, clk_name, NULL); 232 + } 233 + } 234 + CLK_OF_DECLARE(sun6i_a31_ahb1, "allwinner,sun6i-a31-ahb1-clk", sun6i_ahb1_clk_setup); 27 235 28 236 /* Maximum number of parents our clocks have */ 29 237 #define SUNXI_MAX_PARENTS 5 ··· 563 355 } 564 356 565 357 /** 566 - * clk_sunxi_mmc_phase_control() - configures MMC clock phase control 567 - */ 568 - 569 - void clk_sunxi_mmc_phase_control(struct clk *clk, u8 sample, u8 output) 570 - { 571 - #define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw) 572 - #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw) 573 - 574 - struct clk_hw *hw = __clk_get_hw(clk); 575 - struct clk_composite *composite = to_clk_composite(hw); 576 - struct clk_hw *rate_hw = composite->rate_hw; 577 - struct clk_factors *factors = to_clk_factors(rate_hw); 578 - unsigned long flags = 0; 579 - u32 reg; 580 - 581 - if (factors->lock) 582 - spin_lock_irqsave(factors->lock, flags); 583 - 584 - reg = readl(factors->reg); 585 - 586 - /* set sample clock phase control */ 587 - reg &= ~(0x7 << 20); 588 - reg |= ((sample & 0x7) << 20); 589 - 590 - /* set output clock phase control */ 591 - reg &= ~(0x7 << 8); 592 - reg |= ((output & 0x7) << 8); 593 - 594 - writel(reg, factors->reg); 595 - 596 - if (factors->lock) 597 - spin_unlock_irqrestore(factors->lock, flags); 598 - } 599 - EXPORT_SYMBOL(clk_sunxi_mmc_phase_control); 600 - 601 - 602 - /** 603 358 * sunxi_factors_clk_setup() - Setup function for factor clocks 604 359 */ 605 360 ··· 584 413 .kwidth = 2, 585 414 .mshift = 0, 586 415 .mwidth = 2, 416 + .n_start = 1, 587 417 }; 588 418 589 419 static struct clk_factors_config sun8i_a23_pll1_config = { ··· 692 520 static struct clk * __init sunxi_factors_clk_setup(struct device_node *node, 693 521 const struct factors_data *data) 694 522 { 695 - return sunxi_factors_register(node, data, &clk_lock); 523 + void __iomem *reg; 524 + 525 + reg = of_iomap(node, 0); 526 + if (!reg) { 527 + pr_err("Could not get registers for factors-clk: %s\n", 528 + node->name); 529 + return NULL; 530 + } 531 + 532 + return sunxi_factors_register(node, data, &clk_lock, reg); 696 533 } 697 534 698 535 ··· 742 561 of_property_read_string(node, "clock-output-names", &clk_name); 743 562 744 563 clk = clk_register_mux(NULL, clk_name, parents, i, 745 - CLK_SET_RATE_NO_REPARENT, reg, 564 + CLK_SET_RATE_PARENT, reg, 746 565 data->shift, SUNXI_MUX_GATE_WIDTH, 747 566 0, &clk_lock); 748 567 ··· 1398 1217 1399 1218 static const char *sun6i_critical_clocks[] __initdata = { 1400 1219 "cpu", 1401 - "ahb1_sdram", 1402 1220 }; 1403 1221 1404 1222 static void __init sun6i_init_clocks(struct device_node *node)
+49 -24
drivers/mmc/host/sunxi-mmc.c
··· 21 21 #include <linux/err.h> 22 22 23 23 #include <linux/clk.h> 24 - #include <linux/clk/sunxi.h> 25 - 26 24 #include <linux/gpio.h> 27 25 #include <linux/platform_device.h> 28 26 #include <linux/spinlock.h> ··· 227 229 /* clock management */ 228 230 struct clk *clk_ahb; 229 231 struct clk *clk_mmc; 232 + struct clk *clk_sample; 233 + struct clk *clk_output; 230 234 231 235 /* irq */ 232 236 spinlock_t lock; ··· 616 616 static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, 617 617 struct mmc_ios *ios) 618 618 { 619 - u32 rate, oclk_dly, rval, sclk_dly, src_clk; 619 + u32 rate, oclk_dly, rval, sclk_dly; 620 620 int ret; 621 621 622 622 rate = clk_round_rate(host->clk_mmc, ios->clock); ··· 642 642 643 643 /* determine delays */ 644 644 if (rate <= 400000) { 645 - oclk_dly = 0; 646 - sclk_dly = 7; 645 + oclk_dly = 180; 646 + sclk_dly = 42; 647 647 } else if (rate <= 25000000) { 648 - oclk_dly = 0; 649 - sclk_dly = 5; 648 + oclk_dly = 180; 649 + sclk_dly = 75; 650 650 } else if (rate <= 50000000) { 651 651 if (ios->timing == MMC_TIMING_UHS_DDR50) { 652 - oclk_dly = 2; 653 - sclk_dly = 4; 652 + oclk_dly = 60; 653 + sclk_dly = 120; 654 654 } else { 655 - oclk_dly = 3; 656 - sclk_dly = 5; 655 + oclk_dly = 90; 656 + sclk_dly = 150; 657 657 } 658 + } else if (rate <= 100000000) { 659 + oclk_dly = 6; 660 + sclk_dly = 24; 661 + } else if (rate <= 200000000) { 662 + oclk_dly = 3; 663 + sclk_dly = 12; 658 664 } else { 659 - /* rate > 50000000 */ 660 - oclk_dly = 2; 661 - sclk_dly = 4; 665 + return -EINVAL; 662 666 } 663 667 664 - src_clk = clk_get_rate(clk_get_parent(host->clk_mmc)); 665 - if (src_clk >= 300000000 && src_clk <= 400000000) { 666 - if (oclk_dly) 667 - oclk_dly--; 668 - if (sclk_dly) 669 - sclk_dly--; 670 - } 671 - 672 - clk_sunxi_mmc_phase_control(host->clk_mmc, sclk_dly, oclk_dly); 668 + clk_set_phase(host->clk_sample, sclk_dly); 669 + clk_set_phase(host->clk_output, oclk_dly); 673 670 674 671 return sunxi_mmc_oclk_onoff(host, 1); 675 672 } ··· 905 908 return PTR_ERR(host->clk_mmc); 906 909 } 907 910 911 + host->clk_output = devm_clk_get(&pdev->dev, "output"); 912 + if (IS_ERR(host->clk_output)) { 913 + dev_err(&pdev->dev, "Could not get output clock\n"); 914 + return PTR_ERR(host->clk_output); 915 + } 916 + 917 + host->clk_sample = devm_clk_get(&pdev->dev, "sample"); 918 + if (IS_ERR(host->clk_sample)) { 919 + dev_err(&pdev->dev, "Could not get sample clock\n"); 920 + return PTR_ERR(host->clk_sample); 921 + } 922 + 908 923 host->reset = devm_reset_control_get(&pdev->dev, "ahb"); 909 924 910 925 ret = clk_prepare_enable(host->clk_ahb); ··· 931 922 goto error_disable_clk_ahb; 932 923 } 933 924 925 + ret = clk_prepare_enable(host->clk_output); 926 + if (ret) { 927 + dev_err(&pdev->dev, "Enable output clk err %d\n", ret); 928 + goto error_disable_clk_mmc; 929 + } 930 + 931 + ret = clk_prepare_enable(host->clk_sample); 932 + if (ret) { 933 + dev_err(&pdev->dev, "Enable sample clk err %d\n", ret); 934 + goto error_disable_clk_output; 935 + } 936 + 934 937 if (!IS_ERR(host->reset)) { 935 938 ret = reset_control_deassert(host->reset); 936 939 if (ret) { 937 940 dev_err(&pdev->dev, "reset err %d\n", ret); 938 - goto error_disable_clk_mmc; 941 + goto error_disable_clk_sample; 939 942 } 940 943 } 941 944 ··· 966 945 error_assert_reset: 967 946 if (!IS_ERR(host->reset)) 968 947 reset_control_assert(host->reset); 948 + error_disable_clk_sample: 949 + clk_disable_unprepare(host->clk_sample); 950 + error_disable_clk_output: 951 + clk_disable_unprepare(host->clk_output); 969 952 error_disable_clk_mmc: 970 953 clk_disable_unprepare(host->clk_mmc); 971 954 error_disable_clk_ahb:
-22
include/linux/clk/sunxi.h
··· 1 - /* 2 - * Copyright 2013 - Hans de Goede <hdegoede@redhat.com> 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - */ 14 - 15 - #ifndef __LINUX_CLK_SUNXI_H_ 16 - #define __LINUX_CLK_SUNXI_H_ 17 - 18 - #include <linux/clk.h> 19 - 20 - void clk_sunxi_mmc_phase_control(struct clk *clk, u8 sample, u8 output); 21 - 22 - #endif