162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * R9A06G032 clock driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2018 Renesas Electronics Europe Limited 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Michel Pollet <michel.pollet@bp.renesas.com>, <buserror@gmail.com> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/clk.h> 1162306a36Sopenharmony_ci#include <linux/clk-provider.h> 1262306a36Sopenharmony_ci#include <linux/delay.h> 1362306a36Sopenharmony_ci#include <linux/init.h> 1462306a36Sopenharmony_ci#include <linux/io.h> 1562306a36Sopenharmony_ci#include <linux/kernel.h> 1662306a36Sopenharmony_ci#include <linux/math64.h> 1762306a36Sopenharmony_ci#include <linux/of.h> 1862306a36Sopenharmony_ci#include <linux/of_address.h> 1962306a36Sopenharmony_ci#include <linux/of_platform.h> 2062306a36Sopenharmony_ci#include <linux/platform_device.h> 2162306a36Sopenharmony_ci#include <linux/pm_clock.h> 2262306a36Sopenharmony_ci#include <linux/pm_domain.h> 2362306a36Sopenharmony_ci#include <linux/slab.h> 2462306a36Sopenharmony_ci#include <linux/soc/renesas/r9a06g032-sysctrl.h> 2562306a36Sopenharmony_ci#include <linux/spinlock.h> 2662306a36Sopenharmony_ci#include <dt-bindings/clock/r9a06g032-sysctrl.h> 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define R9A06G032_SYSCTRL_USB 0x00 2962306a36Sopenharmony_ci#define R9A06G032_SYSCTRL_USB_H2MODE (1<<1) 3062306a36Sopenharmony_ci#define R9A06G032_SYSCTRL_DMAMUX 0xA0 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/** 3362306a36Sopenharmony_ci * struct regbit - describe one bit in a register 3462306a36Sopenharmony_ci * @reg: offset of register relative to base address, 3562306a36Sopenharmony_ci * expressed in units of 32-bit words (not bytes), 3662306a36Sopenharmony_ci * @bit: which bit (0 to 31) in the register 3762306a36Sopenharmony_ci * 3862306a36Sopenharmony_ci * This structure is used to compactly encode the location 3962306a36Sopenharmony_ci * of a single bit in a register. Five bits are needed to 4062306a36Sopenharmony_ci * encode the bit number. With uint16_t data type, this 4162306a36Sopenharmony_ci * leaves 11 bits to encode a register offset up to 2047. 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * Since registers are aligned on 32-bit boundaries, the 4462306a36Sopenharmony_ci * offset will be specified in 32-bit words rather than bytes. 4562306a36Sopenharmony_ci * This allows encoding an offset up to 0x1FFC (8188) bytes. 4662306a36Sopenharmony_ci * 4762306a36Sopenharmony_ci * Helper macro RB() takes care of converting the register 4862306a36Sopenharmony_ci * offset from bytes to 32-bit words. 4962306a36Sopenharmony_ci */ 5062306a36Sopenharmony_cistruct regbit { 5162306a36Sopenharmony_ci u16 bit:5; 5262306a36Sopenharmony_ci u16 reg:11; 5362306a36Sopenharmony_ci}; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#define RB(_reg, _bit) ((struct regbit) { \ 5662306a36Sopenharmony_ci .reg = (_reg) / 4, \ 5762306a36Sopenharmony_ci .bit = (_bit) \ 5862306a36Sopenharmony_ci}) 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/** 6162306a36Sopenharmony_ci * struct r9a06g032_gate - clock-related control bits 6262306a36Sopenharmony_ci * @gate: clock enable/disable 6362306a36Sopenharmony_ci * @reset: clock module reset (active low) 6462306a36Sopenharmony_ci * @ready: enables NoC forwarding of read/write requests to device, 6562306a36Sopenharmony_ci * (eg. device is ready to handle read/write requests) 6662306a36Sopenharmony_ci * @midle: request to idle the NoC interconnect 6762306a36Sopenharmony_ci * 6862306a36Sopenharmony_ci * Each of these fields describes a single bit in a register, 6962306a36Sopenharmony_ci * which controls some aspect of clock gating. The @gate field 7062306a36Sopenharmony_ci * is mandatory, this one enables/disables the clock. The 7162306a36Sopenharmony_ci * other fields are optional, with zero indicating "not used". 7262306a36Sopenharmony_ci * 7362306a36Sopenharmony_ci * In most cases there is a @reset bit which needs to be 7462306a36Sopenharmony_ci * de-asserted to bring the module out of reset. 7562306a36Sopenharmony_ci * 7662306a36Sopenharmony_ci * Modules may also need to signal when they are @ready to 7762306a36Sopenharmony_ci * handle requests (read/writes) from the NoC interconnect. 7862306a36Sopenharmony_ci * 7962306a36Sopenharmony_ci * Similarly, the @midle bit is used to idle the master. 8062306a36Sopenharmony_ci */ 8162306a36Sopenharmony_cistruct r9a06g032_gate { 8262306a36Sopenharmony_ci struct regbit gate, reset, ready, midle; 8362306a36Sopenharmony_ci /* Unused fields omitted to save space */ 8462306a36Sopenharmony_ci /* struct regbit scon, mirack, mistat */; 8562306a36Sopenharmony_ci}; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cienum gate_type { 8862306a36Sopenharmony_ci K_GATE = 0, /* gate which enable/disable */ 8962306a36Sopenharmony_ci K_FFC, /* fixed factor clock */ 9062306a36Sopenharmony_ci K_DIV, /* divisor */ 9162306a36Sopenharmony_ci K_BITSEL, /* special for UARTs */ 9262306a36Sopenharmony_ci K_DUALGATE /* special for UARTs */ 9362306a36Sopenharmony_ci}; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci/** 9662306a36Sopenharmony_ci * struct r9a06g032_clkdesc - describe a single clock 9762306a36Sopenharmony_ci * @name: string describing this clock 9862306a36Sopenharmony_ci * @managed: boolean indicating if this clock should be 9962306a36Sopenharmony_ci * started/stopped as part of power management 10062306a36Sopenharmony_ci * @type: see enum @gate_type 10162306a36Sopenharmony_ci * @index: the ID of this clock element 10262306a36Sopenharmony_ci * @source: the ID+1 of the parent clock element. 10362306a36Sopenharmony_ci * Root clock uses ID of ~0 (PARENT_ID); 10462306a36Sopenharmony_ci * @gate: clock enable/disable 10562306a36Sopenharmony_ci * @div_min: smallest permitted clock divider 10662306a36Sopenharmony_ci * @div_max: largest permitted clock divider 10762306a36Sopenharmony_ci * @reg: clock divider register offset, in 32-bit words 10862306a36Sopenharmony_ci * @div_table: optional list of fixed clock divider values; 10962306a36Sopenharmony_ci * must be in ascending order, zero for unused 11062306a36Sopenharmony_ci * @div: divisor for fixed-factor clock 11162306a36Sopenharmony_ci * @mul: multiplier for fixed-factor clock 11262306a36Sopenharmony_ci * @group: UART group, 0=UART0/1/2, 1=UART3/4/5/6/7 11362306a36Sopenharmony_ci * @sel: select either g1/r1 or g2/r2 as clock source 11462306a36Sopenharmony_ci * @g1: 1st source gate (clock enable/disable) 11562306a36Sopenharmony_ci * @r1: 1st source reset (module reset) 11662306a36Sopenharmony_ci * @g2: 2nd source gate (clock enable/disable) 11762306a36Sopenharmony_ci * @r2: 2nd source reset (module reset) 11862306a36Sopenharmony_ci * 11962306a36Sopenharmony_ci * Describes a single element in the clock tree hierarchy. 12062306a36Sopenharmony_ci * As there are quite a large number of clock elements, this 12162306a36Sopenharmony_ci * structure is packed tightly to conserve space. 12262306a36Sopenharmony_ci */ 12362306a36Sopenharmony_cistruct r9a06g032_clkdesc { 12462306a36Sopenharmony_ci const char *name; 12562306a36Sopenharmony_ci uint32_t managed:1; 12662306a36Sopenharmony_ci enum gate_type type:3; 12762306a36Sopenharmony_ci uint32_t index:8; 12862306a36Sopenharmony_ci uint32_t source:8; /* source index + 1 (0 == none) */ 12962306a36Sopenharmony_ci union { 13062306a36Sopenharmony_ci /* type = K_GATE */ 13162306a36Sopenharmony_ci struct r9a06g032_gate gate; 13262306a36Sopenharmony_ci /* type = K_DIV */ 13362306a36Sopenharmony_ci struct { 13462306a36Sopenharmony_ci unsigned int div_min:10, div_max:10, reg:10; 13562306a36Sopenharmony_ci u16 div_table[4]; 13662306a36Sopenharmony_ci }; 13762306a36Sopenharmony_ci /* type = K_FFC */ 13862306a36Sopenharmony_ci struct { 13962306a36Sopenharmony_ci u16 div, mul; 14062306a36Sopenharmony_ci }; 14162306a36Sopenharmony_ci /* type = K_DUALGATE */ 14262306a36Sopenharmony_ci struct { 14362306a36Sopenharmony_ci uint16_t group:1; 14462306a36Sopenharmony_ci struct regbit sel, g1, r1, g2, r2; 14562306a36Sopenharmony_ci } dual; 14662306a36Sopenharmony_ci }; 14762306a36Sopenharmony_ci}; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci/* 15062306a36Sopenharmony_ci * The last three arguments are not currently used, 15162306a36Sopenharmony_ci * but are kept in the r9a06g032_clocks table below. 15262306a36Sopenharmony_ci */ 15362306a36Sopenharmony_ci#define I_GATE(_clk, _rst, _rdy, _midle, _scon, _mirack, _mistat) { \ 15462306a36Sopenharmony_ci .gate = _clk, \ 15562306a36Sopenharmony_ci .reset = _rst, \ 15662306a36Sopenharmony_ci .ready = _rdy, \ 15762306a36Sopenharmony_ci .midle = _midle, \ 15862306a36Sopenharmony_ci /* .scon = _scon, */ \ 15962306a36Sopenharmony_ci /* .mirack = _mirack, */ \ 16062306a36Sopenharmony_ci /* .mistat = _mistat */ \ 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci#define D_GATE(_idx, _n, _src, ...) { \ 16362306a36Sopenharmony_ci .type = K_GATE, \ 16462306a36Sopenharmony_ci .index = R9A06G032_##_idx, \ 16562306a36Sopenharmony_ci .source = 1 + R9A06G032_##_src, \ 16662306a36Sopenharmony_ci .name = _n, \ 16762306a36Sopenharmony_ci .gate = I_GATE(__VA_ARGS__) \ 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci#define D_MODULE(_idx, _n, _src, ...) { \ 17062306a36Sopenharmony_ci .type = K_GATE, \ 17162306a36Sopenharmony_ci .index = R9A06G032_##_idx, \ 17262306a36Sopenharmony_ci .source = 1 + R9A06G032_##_src, \ 17362306a36Sopenharmony_ci .name = _n, \ 17462306a36Sopenharmony_ci .managed = 1, \ 17562306a36Sopenharmony_ci .gate = I_GATE(__VA_ARGS__) \ 17662306a36Sopenharmony_ci} 17762306a36Sopenharmony_ci#define D_ROOT(_idx, _n, _mul, _div) { \ 17862306a36Sopenharmony_ci .type = K_FFC, \ 17962306a36Sopenharmony_ci .index = R9A06G032_##_idx, \ 18062306a36Sopenharmony_ci .name = _n, \ 18162306a36Sopenharmony_ci .div = _div, \ 18262306a36Sopenharmony_ci .mul = _mul \ 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci#define D_FFC(_idx, _n, _src, _div) { \ 18562306a36Sopenharmony_ci .type = K_FFC, \ 18662306a36Sopenharmony_ci .index = R9A06G032_##_idx, \ 18762306a36Sopenharmony_ci .source = 1 + R9A06G032_##_src, \ 18862306a36Sopenharmony_ci .name = _n, \ 18962306a36Sopenharmony_ci .div = _div, \ 19062306a36Sopenharmony_ci .mul = 1 \ 19162306a36Sopenharmony_ci} 19262306a36Sopenharmony_ci#define D_DIV(_idx, _n, _src, _reg, _min, _max, ...) { \ 19362306a36Sopenharmony_ci .type = K_DIV, \ 19462306a36Sopenharmony_ci .index = R9A06G032_##_idx, \ 19562306a36Sopenharmony_ci .source = 1 + R9A06G032_##_src, \ 19662306a36Sopenharmony_ci .name = _n, \ 19762306a36Sopenharmony_ci .reg = _reg, \ 19862306a36Sopenharmony_ci .div_min = _min, \ 19962306a36Sopenharmony_ci .div_max = _max, \ 20062306a36Sopenharmony_ci .div_table = { __VA_ARGS__ } \ 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ci#define D_UGATE(_idx, _n, _src, _g, _g1, _r1, _g2, _r2) { \ 20362306a36Sopenharmony_ci .type = K_DUALGATE, \ 20462306a36Sopenharmony_ci .index = R9A06G032_##_idx, \ 20562306a36Sopenharmony_ci .source = 1 + R9A06G032_##_src, \ 20662306a36Sopenharmony_ci .name = _n, \ 20762306a36Sopenharmony_ci .dual = { \ 20862306a36Sopenharmony_ci .group = _g, \ 20962306a36Sopenharmony_ci .g1 = _g1, \ 21062306a36Sopenharmony_ci .r1 = _r1, \ 21162306a36Sopenharmony_ci .g2 = _g2, \ 21262306a36Sopenharmony_ci .r2 = _r2 \ 21362306a36Sopenharmony_ci }, \ 21462306a36Sopenharmony_ci} 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci/* Internal clock IDs */ 21762306a36Sopenharmony_ci#define R9A06G032_CLKOUT 0 21862306a36Sopenharmony_ci#define R9A06G032_CLKOUT_D10 2 21962306a36Sopenharmony_ci#define R9A06G032_CLKOUT_D16 3 22062306a36Sopenharmony_ci#define R9A06G032_CLKOUT_D160 4 22162306a36Sopenharmony_ci#define R9A06G032_CLKOUT_D1OR2 5 22262306a36Sopenharmony_ci#define R9A06G032_CLKOUT_D20 6 22362306a36Sopenharmony_ci#define R9A06G032_CLKOUT_D40 7 22462306a36Sopenharmony_ci#define R9A06G032_CLKOUT_D5 8 22562306a36Sopenharmony_ci#define R9A06G032_CLKOUT_D8 9 22662306a36Sopenharmony_ci#define R9A06G032_DIV_ADC 10 22762306a36Sopenharmony_ci#define R9A06G032_DIV_I2C 11 22862306a36Sopenharmony_ci#define R9A06G032_DIV_NAND 12 22962306a36Sopenharmony_ci#define R9A06G032_DIV_P1_PG 13 23062306a36Sopenharmony_ci#define R9A06G032_DIV_P2_PG 14 23162306a36Sopenharmony_ci#define R9A06G032_DIV_P3_PG 15 23262306a36Sopenharmony_ci#define R9A06G032_DIV_P4_PG 16 23362306a36Sopenharmony_ci#define R9A06G032_DIV_P5_PG 17 23462306a36Sopenharmony_ci#define R9A06G032_DIV_P6_PG 18 23562306a36Sopenharmony_ci#define R9A06G032_DIV_QSPI0 19 23662306a36Sopenharmony_ci#define R9A06G032_DIV_QSPI1 20 23762306a36Sopenharmony_ci#define R9A06G032_DIV_REF_SYNC 21 23862306a36Sopenharmony_ci#define R9A06G032_DIV_SDIO0 22 23962306a36Sopenharmony_ci#define R9A06G032_DIV_SDIO1 23 24062306a36Sopenharmony_ci#define R9A06G032_DIV_SWITCH 24 24162306a36Sopenharmony_ci#define R9A06G032_DIV_UART 25 24262306a36Sopenharmony_ci#define R9A06G032_DIV_MOTOR 64 24362306a36Sopenharmony_ci#define R9A06G032_CLK_DDRPHY_PLLCLK_D4 78 24462306a36Sopenharmony_ci#define R9A06G032_CLK_ECAT100_D4 79 24562306a36Sopenharmony_ci#define R9A06G032_CLK_HSR100_D2 80 24662306a36Sopenharmony_ci#define R9A06G032_CLK_REF_SYNC_D4 81 24762306a36Sopenharmony_ci#define R9A06G032_CLK_REF_SYNC_D8 82 24862306a36Sopenharmony_ci#define R9A06G032_CLK_SERCOS100_D2 83 24962306a36Sopenharmony_ci#define R9A06G032_DIV_CA7 84 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci#define R9A06G032_UART_GROUP_012 154 25262306a36Sopenharmony_ci#define R9A06G032_UART_GROUP_34567 155 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci#define R9A06G032_CLOCK_COUNT (R9A06G032_UART_GROUP_34567 + 1) 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic const struct r9a06g032_clkdesc r9a06g032_clocks[] = { 25762306a36Sopenharmony_ci D_ROOT(CLKOUT, "clkout", 25, 1), 25862306a36Sopenharmony_ci D_ROOT(CLK_PLL_USB, "clk_pll_usb", 12, 10), 25962306a36Sopenharmony_ci D_FFC(CLKOUT_D10, "clkout_d10", CLKOUT, 10), 26062306a36Sopenharmony_ci D_FFC(CLKOUT_D16, "clkout_d16", CLKOUT, 16), 26162306a36Sopenharmony_ci D_FFC(CLKOUT_D160, "clkout_d160", CLKOUT, 160), 26262306a36Sopenharmony_ci D_DIV(CLKOUT_D1OR2, "clkout_d1or2", CLKOUT, 0, 1, 2), 26362306a36Sopenharmony_ci D_FFC(CLKOUT_D20, "clkout_d20", CLKOUT, 20), 26462306a36Sopenharmony_ci D_FFC(CLKOUT_D40, "clkout_d40", CLKOUT, 40), 26562306a36Sopenharmony_ci D_FFC(CLKOUT_D5, "clkout_d5", CLKOUT, 5), 26662306a36Sopenharmony_ci D_FFC(CLKOUT_D8, "clkout_d8", CLKOUT, 8), 26762306a36Sopenharmony_ci D_DIV(DIV_ADC, "div_adc", CLKOUT, 77, 50, 250), 26862306a36Sopenharmony_ci D_DIV(DIV_I2C, "div_i2c", CLKOUT, 78, 12, 16), 26962306a36Sopenharmony_ci D_DIV(DIV_NAND, "div_nand", CLKOUT, 82, 12, 32), 27062306a36Sopenharmony_ci D_DIV(DIV_P1_PG, "div_p1_pg", CLKOUT, 68, 12, 200), 27162306a36Sopenharmony_ci D_DIV(DIV_P2_PG, "div_p2_pg", CLKOUT, 62, 12, 128), 27262306a36Sopenharmony_ci D_DIV(DIV_P3_PG, "div_p3_pg", CLKOUT, 64, 8, 128), 27362306a36Sopenharmony_ci D_DIV(DIV_P4_PG, "div_p4_pg", CLKOUT, 66, 8, 128), 27462306a36Sopenharmony_ci D_DIV(DIV_P5_PG, "div_p5_pg", CLKOUT, 71, 10, 40), 27562306a36Sopenharmony_ci D_DIV(DIV_P6_PG, "div_p6_pg", CLKOUT, 18, 12, 64), 27662306a36Sopenharmony_ci D_DIV(DIV_QSPI0, "div_qspi0", CLKOUT, 73, 3, 7), 27762306a36Sopenharmony_ci D_DIV(DIV_QSPI1, "div_qspi1", CLKOUT, 25, 3, 7), 27862306a36Sopenharmony_ci D_DIV(DIV_REF_SYNC, "div_ref_sync", CLKOUT, 56, 2, 16, 2, 4, 8, 16), 27962306a36Sopenharmony_ci D_DIV(DIV_SDIO0, "div_sdio0", CLKOUT, 74, 20, 128), 28062306a36Sopenharmony_ci D_DIV(DIV_SDIO1, "div_sdio1", CLKOUT, 75, 20, 128), 28162306a36Sopenharmony_ci D_DIV(DIV_SWITCH, "div_switch", CLKOUT, 37, 5, 40), 28262306a36Sopenharmony_ci D_DIV(DIV_UART, "div_uart", CLKOUT, 79, 12, 128), 28362306a36Sopenharmony_ci D_GATE(CLK_25_PG4, "clk_25_pg4", CLKOUT_D40, RB(0xe8, 9), 28462306a36Sopenharmony_ci RB(0xe8, 10), RB(0xe8, 11), RB(0x00, 0), 28562306a36Sopenharmony_ci RB(0x15c, 3), RB(0x00, 0), RB(0x00, 0)), 28662306a36Sopenharmony_ci D_GATE(CLK_25_PG5, "clk_25_pg5", CLKOUT_D40, RB(0xe8, 12), 28762306a36Sopenharmony_ci RB(0xe8, 13), RB(0xe8, 14), RB(0x00, 0), 28862306a36Sopenharmony_ci RB(0x15c, 4), RB(0x00, 0), RB(0x00, 0)), 28962306a36Sopenharmony_ci D_GATE(CLK_25_PG6, "clk_25_pg6", CLKOUT_D40, RB(0xe8, 15), 29062306a36Sopenharmony_ci RB(0xe8, 16), RB(0xe8, 17), RB(0x00, 0), 29162306a36Sopenharmony_ci RB(0x15c, 5), RB(0x00, 0), RB(0x00, 0)), 29262306a36Sopenharmony_ci D_GATE(CLK_25_PG7, "clk_25_pg7", CLKOUT_D40, RB(0xe8, 18), 29362306a36Sopenharmony_ci RB(0xe8, 19), RB(0xe8, 20), RB(0x00, 0), 29462306a36Sopenharmony_ci RB(0x15c, 6), RB(0x00, 0), RB(0x00, 0)), 29562306a36Sopenharmony_ci D_GATE(CLK_25_PG8, "clk_25_pg8", CLKOUT_D40, RB(0xe8, 21), 29662306a36Sopenharmony_ci RB(0xe8, 22), RB(0xe8, 23), RB(0x00, 0), 29762306a36Sopenharmony_ci RB(0x15c, 7), RB(0x00, 0), RB(0x00, 0)), 29862306a36Sopenharmony_ci D_GATE(CLK_ADC, "clk_adc", DIV_ADC, RB(0x3c, 10), 29962306a36Sopenharmony_ci RB(0x3c, 11), RB(0x00, 0), RB(0x00, 0), 30062306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 30162306a36Sopenharmony_ci D_GATE(CLK_ECAT100, "clk_ecat100", CLKOUT_D10, RB(0x80, 5), 30262306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0), 30362306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 30462306a36Sopenharmony_ci D_GATE(CLK_HSR100, "clk_hsr100", CLKOUT_D10, RB(0x90, 3), 30562306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0), 30662306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 30762306a36Sopenharmony_ci D_GATE(CLK_I2C0, "clk_i2c0", DIV_I2C, RB(0x3c, 6), 30862306a36Sopenharmony_ci RB(0x3c, 7), RB(0x00, 0), RB(0x00, 0), 30962306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 31062306a36Sopenharmony_ci D_GATE(CLK_I2C1, "clk_i2c1", DIV_I2C, RB(0x3c, 8), 31162306a36Sopenharmony_ci RB(0x3c, 9), RB(0x00, 0), RB(0x00, 0), 31262306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 31362306a36Sopenharmony_ci D_GATE(CLK_MII_REF, "clk_mii_ref", CLKOUT_D40, RB(0x68, 2), 31462306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0), 31562306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 31662306a36Sopenharmony_ci D_GATE(CLK_NAND, "clk_nand", DIV_NAND, RB(0x50, 4), 31762306a36Sopenharmony_ci RB(0x50, 5), RB(0x00, 0), RB(0x00, 0), 31862306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 31962306a36Sopenharmony_ci D_GATE(CLK_NOUSBP2_PG6, "clk_nousbp2_pg6", DIV_P2_PG, RB(0xec, 20), 32062306a36Sopenharmony_ci RB(0xec, 21), RB(0x00, 0), RB(0x00, 0), 32162306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 32262306a36Sopenharmony_ci D_GATE(CLK_P1_PG2, "clk_p1_pg2", DIV_P1_PG, RB(0x10c, 2), 32362306a36Sopenharmony_ci RB(0x10c, 3), RB(0x00, 0), RB(0x00, 0), 32462306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 32562306a36Sopenharmony_ci D_GATE(CLK_P1_PG3, "clk_p1_pg3", DIV_P1_PG, RB(0x10c, 4), 32662306a36Sopenharmony_ci RB(0x10c, 5), RB(0x00, 0), RB(0x00, 0), 32762306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 32862306a36Sopenharmony_ci D_GATE(CLK_P1_PG4, "clk_p1_pg4", DIV_P1_PG, RB(0x10c, 6), 32962306a36Sopenharmony_ci RB(0x10c, 7), RB(0x00, 0), RB(0x00, 0), 33062306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 33162306a36Sopenharmony_ci D_GATE(CLK_P4_PG3, "clk_p4_pg3", DIV_P4_PG, RB(0x104, 4), 33262306a36Sopenharmony_ci RB(0x104, 5), RB(0x00, 0), RB(0x00, 0), 33362306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 33462306a36Sopenharmony_ci D_GATE(CLK_P4_PG4, "clk_p4_pg4", DIV_P4_PG, RB(0x104, 6), 33562306a36Sopenharmony_ci RB(0x104, 7), RB(0x00, 0), RB(0x00, 0), 33662306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 33762306a36Sopenharmony_ci D_GATE(CLK_P6_PG1, "clk_p6_pg1", DIV_P6_PG, RB(0x114, 0), 33862306a36Sopenharmony_ci RB(0x114, 1), RB(0x114, 2), RB(0x00, 0), 33962306a36Sopenharmony_ci RB(0x16c, 0), RB(0x00, 0), RB(0x00, 0)), 34062306a36Sopenharmony_ci D_GATE(CLK_P6_PG2, "clk_p6_pg2", DIV_P6_PG, RB(0x114, 3), 34162306a36Sopenharmony_ci RB(0x114, 4), RB(0x114, 5), RB(0x00, 0), 34262306a36Sopenharmony_ci RB(0x16c, 1), RB(0x00, 0), RB(0x00, 0)), 34362306a36Sopenharmony_ci D_GATE(CLK_P6_PG3, "clk_p6_pg3", DIV_P6_PG, RB(0x114, 6), 34462306a36Sopenharmony_ci RB(0x114, 7), RB(0x114, 8), RB(0x00, 0), 34562306a36Sopenharmony_ci RB(0x16c, 2), RB(0x00, 0), RB(0x00, 0)), 34662306a36Sopenharmony_ci D_GATE(CLK_P6_PG4, "clk_p6_pg4", DIV_P6_PG, RB(0x114, 9), 34762306a36Sopenharmony_ci RB(0x114, 10), RB(0x114, 11), RB(0x00, 0), 34862306a36Sopenharmony_ci RB(0x16c, 3), RB(0x00, 0), RB(0x00, 0)), 34962306a36Sopenharmony_ci D_MODULE(CLK_PCI_USB, "clk_pci_usb", CLKOUT_D40, RB(0x1c, 6), 35062306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0), 35162306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 35262306a36Sopenharmony_ci D_GATE(CLK_QSPI0, "clk_qspi0", DIV_QSPI0, RB(0x54, 4), 35362306a36Sopenharmony_ci RB(0x54, 5), RB(0x00, 0), RB(0x00, 0), 35462306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 35562306a36Sopenharmony_ci D_GATE(CLK_QSPI1, "clk_qspi1", DIV_QSPI1, RB(0x90, 4), 35662306a36Sopenharmony_ci RB(0x90, 5), RB(0x00, 0), RB(0x00, 0), 35762306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 35862306a36Sopenharmony_ci D_GATE(CLK_RGMII_REF, "clk_rgmii_ref", CLKOUT_D8, RB(0x68, 0), 35962306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0), 36062306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 36162306a36Sopenharmony_ci D_GATE(CLK_RMII_REF, "clk_rmii_ref", CLKOUT_D20, RB(0x68, 1), 36262306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0), 36362306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 36462306a36Sopenharmony_ci D_GATE(CLK_SDIO0, "clk_sdio0", DIV_SDIO0, RB(0x0c, 4), 36562306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0), 36662306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 36762306a36Sopenharmony_ci D_GATE(CLK_SDIO1, "clk_sdio1", DIV_SDIO1, RB(0xc8, 4), 36862306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0), 36962306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 37062306a36Sopenharmony_ci D_GATE(CLK_SERCOS100, "clk_sercos100", CLKOUT_D10, RB(0x84, 5), 37162306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0), 37262306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 37362306a36Sopenharmony_ci D_GATE(CLK_SLCD, "clk_slcd", DIV_P1_PG, RB(0x10c, 0), 37462306a36Sopenharmony_ci RB(0x10c, 1), RB(0x00, 0), RB(0x00, 0), 37562306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 37662306a36Sopenharmony_ci D_GATE(CLK_SPI0, "clk_spi0", DIV_P3_PG, RB(0xfc, 0), 37762306a36Sopenharmony_ci RB(0xfc, 1), RB(0x00, 0), RB(0x00, 0), 37862306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 37962306a36Sopenharmony_ci D_GATE(CLK_SPI1, "clk_spi1", DIV_P3_PG, RB(0xfc, 2), 38062306a36Sopenharmony_ci RB(0xfc, 3), RB(0x00, 0), RB(0x00, 0), 38162306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 38262306a36Sopenharmony_ci D_GATE(CLK_SPI2, "clk_spi2", DIV_P3_PG, RB(0xfc, 4), 38362306a36Sopenharmony_ci RB(0xfc, 5), RB(0x00, 0), RB(0x00, 0), 38462306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 38562306a36Sopenharmony_ci D_GATE(CLK_SPI3, "clk_spi3", DIV_P3_PG, RB(0xfc, 6), 38662306a36Sopenharmony_ci RB(0xfc, 7), RB(0x00, 0), RB(0x00, 0), 38762306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 38862306a36Sopenharmony_ci D_GATE(CLK_SPI4, "clk_spi4", DIV_P4_PG, RB(0x104, 0), 38962306a36Sopenharmony_ci RB(0x104, 1), RB(0x00, 0), RB(0x00, 0), 39062306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 39162306a36Sopenharmony_ci D_GATE(CLK_SPI5, "clk_spi5", DIV_P4_PG, RB(0x104, 2), 39262306a36Sopenharmony_ci RB(0x104, 3), RB(0x00, 0), RB(0x00, 0), 39362306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 39462306a36Sopenharmony_ci D_GATE(CLK_SWITCH, "clk_switch", DIV_SWITCH, RB(0x130, 2), 39562306a36Sopenharmony_ci RB(0x130, 3), RB(0x00, 0), RB(0x00, 0), 39662306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 39762306a36Sopenharmony_ci D_DIV(DIV_MOTOR, "div_motor", CLKOUT_D5, 84, 2, 8), 39862306a36Sopenharmony_ci D_MODULE(HCLK_ECAT125, "hclk_ecat125", CLKOUT_D8, RB(0x80, 0), 39962306a36Sopenharmony_ci RB(0x80, 1), RB(0x00, 0), RB(0x80, 2), 40062306a36Sopenharmony_ci RB(0x00, 0), RB(0x88, 0), RB(0x88, 1)), 40162306a36Sopenharmony_ci D_MODULE(HCLK_PINCONFIG, "hclk_pinconfig", CLKOUT_D40, RB(0xe8, 0), 40262306a36Sopenharmony_ci RB(0xe8, 1), RB(0xe8, 2), RB(0x00, 0), 40362306a36Sopenharmony_ci RB(0x15c, 0), RB(0x00, 0), RB(0x00, 0)), 40462306a36Sopenharmony_ci D_MODULE(HCLK_SERCOS, "hclk_sercos", CLKOUT_D10, RB(0x84, 0), 40562306a36Sopenharmony_ci RB(0x84, 2), RB(0x00, 0), RB(0x84, 1), 40662306a36Sopenharmony_ci RB(0x00, 0), RB(0x8c, 0), RB(0x8c, 1)), 40762306a36Sopenharmony_ci D_MODULE(HCLK_SGPIO2, "hclk_sgpio2", DIV_P5_PG, RB(0x118, 3), 40862306a36Sopenharmony_ci RB(0x118, 4), RB(0x118, 5), RB(0x00, 0), 40962306a36Sopenharmony_ci RB(0x168, 1), RB(0x00, 0), RB(0x00, 0)), 41062306a36Sopenharmony_ci D_MODULE(HCLK_SGPIO3, "hclk_sgpio3", DIV_P5_PG, RB(0x118, 6), 41162306a36Sopenharmony_ci RB(0x118, 7), RB(0x118, 8), RB(0x00, 0), 41262306a36Sopenharmony_ci RB(0x168, 2), RB(0x00, 0), RB(0x00, 0)), 41362306a36Sopenharmony_ci D_MODULE(HCLK_SGPIO4, "hclk_sgpio4", DIV_P5_PG, RB(0x118, 9), 41462306a36Sopenharmony_ci RB(0x118, 10), RB(0x118, 11), RB(0x00, 0), 41562306a36Sopenharmony_ci RB(0x168, 3), RB(0x00, 0), RB(0x00, 0)), 41662306a36Sopenharmony_ci D_MODULE(HCLK_TIMER0, "hclk_timer0", CLKOUT_D40, RB(0xe8, 3), 41762306a36Sopenharmony_ci RB(0xe8, 4), RB(0xe8, 5), RB(0x00, 0), 41862306a36Sopenharmony_ci RB(0x15c, 1), RB(0x00, 0), RB(0x00, 0)), 41962306a36Sopenharmony_ci D_MODULE(HCLK_TIMER1, "hclk_timer1", CLKOUT_D40, RB(0xe8, 6), 42062306a36Sopenharmony_ci RB(0xe8, 7), RB(0xe8, 8), RB(0x00, 0), 42162306a36Sopenharmony_ci RB(0x15c, 2), RB(0x00, 0), RB(0x00, 0)), 42262306a36Sopenharmony_ci D_MODULE(HCLK_USBF, "hclk_usbf", CLKOUT_D8, RB(0x1c, 3), 42362306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x1c, 4), 42462306a36Sopenharmony_ci RB(0x00, 0), RB(0x20, 2), RB(0x20, 3)), 42562306a36Sopenharmony_ci D_MODULE(HCLK_USBH, "hclk_usbh", CLKOUT_D8, RB(0x1c, 0), 42662306a36Sopenharmony_ci RB(0x1c, 1), RB(0x00, 0), RB(0x1c, 2), 42762306a36Sopenharmony_ci RB(0x00, 0), RB(0x20, 0), RB(0x20, 1)), 42862306a36Sopenharmony_ci D_MODULE(HCLK_USBPM, "hclk_usbpm", CLKOUT_D8, RB(0x1c, 5), 42962306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0), 43062306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 43162306a36Sopenharmony_ci D_GATE(CLK_48_PG_F, "clk_48_pg_f", CLK_48, RB(0xf0, 12), 43262306a36Sopenharmony_ci RB(0xf0, 13), RB(0x00, 0), RB(0xf0, 14), 43362306a36Sopenharmony_ci RB(0x00, 0), RB(0x160, 4), RB(0x160, 5)), 43462306a36Sopenharmony_ci D_GATE(CLK_48_PG4, "clk_48_pg4", CLK_48, RB(0xf0, 9), 43562306a36Sopenharmony_ci RB(0xf0, 10), RB(0xf0, 11), RB(0x00, 0), 43662306a36Sopenharmony_ci RB(0x160, 3), RB(0x00, 0), RB(0x00, 0)), 43762306a36Sopenharmony_ci D_FFC(CLK_DDRPHY_PLLCLK_D4, "clk_ddrphy_pllclk_d4", CLK_DDRPHY_PLLCLK, 4), 43862306a36Sopenharmony_ci D_FFC(CLK_ECAT100_D4, "clk_ecat100_d4", CLK_ECAT100, 4), 43962306a36Sopenharmony_ci D_FFC(CLK_HSR100_D2, "clk_hsr100_d2", CLK_HSR100, 2), 44062306a36Sopenharmony_ci D_FFC(CLK_REF_SYNC_D4, "clk_ref_sync_d4", CLK_REF_SYNC, 4), 44162306a36Sopenharmony_ci D_FFC(CLK_REF_SYNC_D8, "clk_ref_sync_d8", CLK_REF_SYNC, 8), 44262306a36Sopenharmony_ci D_FFC(CLK_SERCOS100_D2, "clk_sercos100_d2", CLK_SERCOS100, 2), 44362306a36Sopenharmony_ci D_DIV(DIV_CA7, "div_ca7", CLK_REF_SYNC, 57, 1, 4, 1, 2, 4), 44462306a36Sopenharmony_ci D_MODULE(HCLK_CAN0, "hclk_can0", CLK_48, RB(0xf0, 3), 44562306a36Sopenharmony_ci RB(0xf0, 4), RB(0xf0, 5), RB(0x00, 0), 44662306a36Sopenharmony_ci RB(0x160, 1), RB(0x00, 0), RB(0x00, 0)), 44762306a36Sopenharmony_ci D_MODULE(HCLK_CAN1, "hclk_can1", CLK_48, RB(0xf0, 6), 44862306a36Sopenharmony_ci RB(0xf0, 7), RB(0xf0, 8), RB(0x00, 0), 44962306a36Sopenharmony_ci RB(0x160, 2), RB(0x00, 0), RB(0x00, 0)), 45062306a36Sopenharmony_ci D_MODULE(HCLK_DELTASIGMA, "hclk_deltasigma", DIV_MOTOR, RB(0x3c, 15), 45162306a36Sopenharmony_ci RB(0x3c, 16), RB(0x3c, 17), RB(0x00, 0), 45262306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 45362306a36Sopenharmony_ci D_MODULE(HCLK_PWMPTO, "hclk_pwmpto", DIV_MOTOR, RB(0x3c, 12), 45462306a36Sopenharmony_ci RB(0x3c, 13), RB(0x3c, 14), RB(0x00, 0), 45562306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 45662306a36Sopenharmony_ci D_MODULE(HCLK_RSV, "hclk_rsv", CLK_48, RB(0xf0, 0), 45762306a36Sopenharmony_ci RB(0xf0, 1), RB(0xf0, 2), RB(0x00, 0), 45862306a36Sopenharmony_ci RB(0x160, 0), RB(0x00, 0), RB(0x00, 0)), 45962306a36Sopenharmony_ci D_MODULE(HCLK_SGPIO0, "hclk_sgpio0", DIV_MOTOR, RB(0x3c, 0), 46062306a36Sopenharmony_ci RB(0x3c, 1), RB(0x3c, 2), RB(0x00, 0), 46162306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 46262306a36Sopenharmony_ci D_MODULE(HCLK_SGPIO1, "hclk_sgpio1", DIV_MOTOR, RB(0x3c, 3), 46362306a36Sopenharmony_ci RB(0x3c, 4), RB(0x3c, 5), RB(0x00, 0), 46462306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 46562306a36Sopenharmony_ci D_DIV(RTOS_MDC, "rtos_mdc", CLK_REF_SYNC, 100, 80, 640, 80, 160, 320, 640), 46662306a36Sopenharmony_ci D_GATE(CLK_CM3, "clk_cm3", CLK_REF_SYNC_D4, RB(0x174, 0), 46762306a36Sopenharmony_ci RB(0x174, 1), RB(0x00, 0), RB(0x174, 2), 46862306a36Sopenharmony_ci RB(0x00, 0), RB(0x178, 0), RB(0x178, 1)), 46962306a36Sopenharmony_ci D_GATE(CLK_DDRC, "clk_ddrc", CLK_DDRPHY_PLLCLK_D4, RB(0x64, 3), 47062306a36Sopenharmony_ci RB(0x64, 4), RB(0x00, 0), RB(0x00, 0), 47162306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 47262306a36Sopenharmony_ci D_GATE(CLK_ECAT25, "clk_ecat25", CLK_ECAT100_D4, RB(0x80, 3), 47362306a36Sopenharmony_ci RB(0x80, 4), RB(0x00, 0), RB(0x00, 0), 47462306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 47562306a36Sopenharmony_ci D_GATE(CLK_HSR50, "clk_hsr50", CLK_HSR100_D2, RB(0x90, 4), 47662306a36Sopenharmony_ci RB(0x90, 5), RB(0x00, 0), RB(0x00, 0), 47762306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 47862306a36Sopenharmony_ci D_GATE(CLK_HW_RTOS, "clk_hw_rtos", CLK_REF_SYNC_D4, RB(0x18c, 0), 47962306a36Sopenharmony_ci RB(0x18c, 1), RB(0x00, 0), RB(0x00, 0), 48062306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 48162306a36Sopenharmony_ci D_GATE(CLK_SERCOS50, "clk_sercos50", CLK_SERCOS100_D2, RB(0x84, 4), 48262306a36Sopenharmony_ci RB(0x84, 3), RB(0x00, 0), RB(0x00, 0), 48362306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 48462306a36Sopenharmony_ci D_MODULE(HCLK_ADC, "hclk_adc", CLK_REF_SYNC_D8, RB(0x34, 15), 48562306a36Sopenharmony_ci RB(0x34, 16), RB(0x34, 17), RB(0x00, 0), 48662306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 48762306a36Sopenharmony_ci D_MODULE(HCLK_CM3, "hclk_cm3", CLK_REF_SYNC_D4, RB(0x184, 0), 48862306a36Sopenharmony_ci RB(0x184, 1), RB(0x184, 2), RB(0x00, 0), 48962306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 49062306a36Sopenharmony_ci D_MODULE(HCLK_CRYPTO_EIP150, "hclk_crypto_eip150", CLK_REF_SYNC_D4, RB(0x24, 3), 49162306a36Sopenharmony_ci RB(0x24, 4), RB(0x24, 5), RB(0x00, 0), 49262306a36Sopenharmony_ci RB(0x28, 2), RB(0x00, 0), RB(0x00, 0)), 49362306a36Sopenharmony_ci D_MODULE(HCLK_CRYPTO_EIP93, "hclk_crypto_eip93", CLK_REF_SYNC_D4, RB(0x24, 0), 49462306a36Sopenharmony_ci RB(0x24, 1), RB(0x00, 0), RB(0x24, 2), 49562306a36Sopenharmony_ci RB(0x00, 0), RB(0x28, 0), RB(0x28, 1)), 49662306a36Sopenharmony_ci D_MODULE(HCLK_DDRC, "hclk_ddrc", CLK_REF_SYNC_D4, RB(0x64, 0), 49762306a36Sopenharmony_ci RB(0x64, 2), RB(0x00, 0), RB(0x64, 1), 49862306a36Sopenharmony_ci RB(0x00, 0), RB(0x74, 0), RB(0x74, 1)), 49962306a36Sopenharmony_ci D_MODULE(HCLK_DMA0, "hclk_dma0", CLK_REF_SYNC_D4, RB(0x4c, 0), 50062306a36Sopenharmony_ci RB(0x4c, 1), RB(0x4c, 2), RB(0x4c, 3), 50162306a36Sopenharmony_ci RB(0x58, 0), RB(0x58, 1), RB(0x58, 2)), 50262306a36Sopenharmony_ci D_MODULE(HCLK_DMA1, "hclk_dma1", CLK_REF_SYNC_D4, RB(0x4c, 4), 50362306a36Sopenharmony_ci RB(0x4c, 5), RB(0x4c, 6), RB(0x4c, 7), 50462306a36Sopenharmony_ci RB(0x58, 3), RB(0x58, 4), RB(0x58, 5)), 50562306a36Sopenharmony_ci D_MODULE(HCLK_GMAC0, "hclk_gmac0", CLK_REF_SYNC_D4, RB(0x6c, 0), 50662306a36Sopenharmony_ci RB(0x6c, 1), RB(0x6c, 2), RB(0x6c, 3), 50762306a36Sopenharmony_ci RB(0x78, 0), RB(0x78, 1), RB(0x78, 2)), 50862306a36Sopenharmony_ci D_MODULE(HCLK_GMAC1, "hclk_gmac1", CLK_REF_SYNC_D4, RB(0x70, 0), 50962306a36Sopenharmony_ci RB(0x70, 1), RB(0x70, 2), RB(0x70, 3), 51062306a36Sopenharmony_ci RB(0x7c, 0), RB(0x7c, 1), RB(0x7c, 2)), 51162306a36Sopenharmony_ci D_MODULE(HCLK_GPIO0, "hclk_gpio0", CLK_REF_SYNC_D4, RB(0x40, 18), 51262306a36Sopenharmony_ci RB(0x40, 19), RB(0x40, 20), RB(0x00, 0), 51362306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 51462306a36Sopenharmony_ci D_MODULE(HCLK_GPIO1, "hclk_gpio1", CLK_REF_SYNC_D4, RB(0x40, 21), 51562306a36Sopenharmony_ci RB(0x40, 22), RB(0x40, 23), RB(0x00, 0), 51662306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 51762306a36Sopenharmony_ci D_MODULE(HCLK_GPIO2, "hclk_gpio2", CLK_REF_SYNC_D4, RB(0x44, 9), 51862306a36Sopenharmony_ci RB(0x44, 10), RB(0x44, 11), RB(0x00, 0), 51962306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 52062306a36Sopenharmony_ci D_MODULE(HCLK_HSR, "hclk_hsr", CLK_HSR100_D2, RB(0x90, 0), 52162306a36Sopenharmony_ci RB(0x90, 2), RB(0x00, 0), RB(0x90, 1), 52262306a36Sopenharmony_ci RB(0x00, 0), RB(0x98, 0), RB(0x98, 1)), 52362306a36Sopenharmony_ci D_MODULE(HCLK_I2C0, "hclk_i2c0", CLK_REF_SYNC_D8, RB(0x34, 9), 52462306a36Sopenharmony_ci RB(0x34, 10), RB(0x34, 11), RB(0x00, 0), 52562306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 52662306a36Sopenharmony_ci D_MODULE(HCLK_I2C1, "hclk_i2c1", CLK_REF_SYNC_D8, RB(0x34, 12), 52762306a36Sopenharmony_ci RB(0x34, 13), RB(0x34, 14), RB(0x00, 0), 52862306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 52962306a36Sopenharmony_ci D_MODULE(HCLK_LCD, "hclk_lcd", CLK_REF_SYNC_D4, RB(0xf4, 0), 53062306a36Sopenharmony_ci RB(0xf4, 1), RB(0xf4, 2), RB(0x00, 0), 53162306a36Sopenharmony_ci RB(0x164, 0), RB(0x00, 0), RB(0x00, 0)), 53262306a36Sopenharmony_ci D_MODULE(HCLK_MSEBI_M, "hclk_msebi_m", CLK_REF_SYNC_D4, RB(0x2c, 4), 53362306a36Sopenharmony_ci RB(0x2c, 5), RB(0x2c, 6), RB(0x00, 0), 53462306a36Sopenharmony_ci RB(0x30, 3), RB(0x00, 0), RB(0x00, 0)), 53562306a36Sopenharmony_ci D_MODULE(HCLK_MSEBI_S, "hclk_msebi_s", CLK_REF_SYNC_D4, RB(0x2c, 0), 53662306a36Sopenharmony_ci RB(0x2c, 1), RB(0x2c, 2), RB(0x2c, 3), 53762306a36Sopenharmony_ci RB(0x30, 0), RB(0x30, 1), RB(0x30, 2)), 53862306a36Sopenharmony_ci D_MODULE(HCLK_NAND, "hclk_nand", CLK_REF_SYNC_D4, RB(0x50, 0), 53962306a36Sopenharmony_ci RB(0x50, 1), RB(0x50, 2), RB(0x50, 3), 54062306a36Sopenharmony_ci RB(0x5c, 0), RB(0x5c, 1), RB(0x5c, 2)), 54162306a36Sopenharmony_ci D_MODULE(HCLK_PG_I, "hclk_pg_i", CLK_REF_SYNC_D4, RB(0xf4, 12), 54262306a36Sopenharmony_ci RB(0xf4, 13), RB(0x00, 0), RB(0xf4, 14), 54362306a36Sopenharmony_ci RB(0x00, 0), RB(0x164, 4), RB(0x164, 5)), 54462306a36Sopenharmony_ci D_MODULE(HCLK_PG19, "hclk_pg19", CLK_REF_SYNC_D4, RB(0x44, 12), 54562306a36Sopenharmony_ci RB(0x44, 13), RB(0x44, 14), RB(0x00, 0), 54662306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 54762306a36Sopenharmony_ci D_MODULE(HCLK_PG20, "hclk_pg20", CLK_REF_SYNC_D4, RB(0x44, 15), 54862306a36Sopenharmony_ci RB(0x44, 16), RB(0x44, 17), RB(0x00, 0), 54962306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 55062306a36Sopenharmony_ci D_MODULE(HCLK_PG3, "hclk_pg3", CLK_REF_SYNC_D4, RB(0xf4, 6), 55162306a36Sopenharmony_ci RB(0xf4, 7), RB(0xf4, 8), RB(0x00, 0), 55262306a36Sopenharmony_ci RB(0x164, 2), RB(0x00, 0), RB(0x00, 0)), 55362306a36Sopenharmony_ci D_MODULE(HCLK_PG4, "hclk_pg4", CLK_REF_SYNC_D4, RB(0xf4, 9), 55462306a36Sopenharmony_ci RB(0xf4, 10), RB(0xf4, 11), RB(0x00, 0), 55562306a36Sopenharmony_ci RB(0x164, 3), RB(0x00, 0), RB(0x00, 0)), 55662306a36Sopenharmony_ci D_MODULE(HCLK_QSPI0, "hclk_qspi0", CLK_REF_SYNC_D4, RB(0x54, 0), 55762306a36Sopenharmony_ci RB(0x54, 1), RB(0x54, 2), RB(0x54, 3), 55862306a36Sopenharmony_ci RB(0x60, 0), RB(0x60, 1), RB(0x60, 2)), 55962306a36Sopenharmony_ci D_MODULE(HCLK_QSPI1, "hclk_qspi1", CLK_REF_SYNC_D4, RB(0x90, 0), 56062306a36Sopenharmony_ci RB(0x90, 1), RB(0x90, 2), RB(0x90, 3), 56162306a36Sopenharmony_ci RB(0x98, 0), RB(0x98, 1), RB(0x98, 2)), 56262306a36Sopenharmony_ci D_MODULE(HCLK_ROM, "hclk_rom", CLK_REF_SYNC_D4, RB(0x154, 0), 56362306a36Sopenharmony_ci RB(0x154, 1), RB(0x154, 2), RB(0x00, 0), 56462306a36Sopenharmony_ci RB(0x170, 0), RB(0x00, 0), RB(0x00, 0)), 56562306a36Sopenharmony_ci D_MODULE(HCLK_RTC, "hclk_rtc", CLK_REF_SYNC_D8, RB(0x140, 0), 56662306a36Sopenharmony_ci RB(0x140, 3), RB(0x00, 0), RB(0x140, 2), 56762306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 56862306a36Sopenharmony_ci D_MODULE(HCLK_SDIO0, "hclk_sdio0", CLK_REF_SYNC_D4, RB(0x0c, 0), 56962306a36Sopenharmony_ci RB(0x0c, 1), RB(0x0c, 2), RB(0x0c, 3), 57062306a36Sopenharmony_ci RB(0x10, 0), RB(0x10, 1), RB(0x10, 2)), 57162306a36Sopenharmony_ci D_MODULE(HCLK_SDIO1, "hclk_sdio1", CLK_REF_SYNC_D4, RB(0xc8, 0), 57262306a36Sopenharmony_ci RB(0xc8, 1), RB(0xc8, 2), RB(0xc8, 3), 57362306a36Sopenharmony_ci RB(0xcc, 0), RB(0xcc, 1), RB(0xcc, 2)), 57462306a36Sopenharmony_ci D_MODULE(HCLK_SEMAP, "hclk_semap", CLK_REF_SYNC_D4, RB(0xf4, 3), 57562306a36Sopenharmony_ci RB(0xf4, 4), RB(0xf4, 5), RB(0x00, 0), 57662306a36Sopenharmony_ci RB(0x164, 1), RB(0x00, 0), RB(0x00, 0)), 57762306a36Sopenharmony_ci D_MODULE(HCLK_SPI0, "hclk_spi0", CLK_REF_SYNC_D4, RB(0x40, 0), 57862306a36Sopenharmony_ci RB(0x40, 1), RB(0x40, 2), RB(0x00, 0), 57962306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 58062306a36Sopenharmony_ci D_MODULE(HCLK_SPI1, "hclk_spi1", CLK_REF_SYNC_D4, RB(0x40, 3), 58162306a36Sopenharmony_ci RB(0x40, 4), RB(0x40, 5), RB(0x00, 0), 58262306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 58362306a36Sopenharmony_ci D_MODULE(HCLK_SPI2, "hclk_spi2", CLK_REF_SYNC_D4, RB(0x40, 6), 58462306a36Sopenharmony_ci RB(0x40, 7), RB(0x40, 8), RB(0x00, 0), 58562306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 58662306a36Sopenharmony_ci D_MODULE(HCLK_SPI3, "hclk_spi3", CLK_REF_SYNC_D4, RB(0x40, 9), 58762306a36Sopenharmony_ci RB(0x40, 10), RB(0x40, 11), RB(0x00, 0), 58862306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 58962306a36Sopenharmony_ci D_MODULE(HCLK_SPI4, "hclk_spi4", CLK_REF_SYNC_D4, RB(0x40, 12), 59062306a36Sopenharmony_ci RB(0x40, 13), RB(0x40, 14), RB(0x00, 0), 59162306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 59262306a36Sopenharmony_ci D_MODULE(HCLK_SPI5, "hclk_spi5", CLK_REF_SYNC_D4, RB(0x40, 15), 59362306a36Sopenharmony_ci RB(0x40, 16), RB(0x40, 17), RB(0x00, 0), 59462306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 59562306a36Sopenharmony_ci D_MODULE(HCLK_SWITCH, "hclk_switch", CLK_REF_SYNC_D4, RB(0x130, 0), 59662306a36Sopenharmony_ci RB(0x00, 0), RB(0x130, 1), RB(0x00, 0), 59762306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 59862306a36Sopenharmony_ci D_MODULE(HCLK_SWITCH_RG, "hclk_switch_rg", CLK_REF_SYNC_D4, RB(0x188, 0), 59962306a36Sopenharmony_ci RB(0x188, 1), RB(0x188, 2), RB(0x00, 0), 60062306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 60162306a36Sopenharmony_ci D_MODULE(HCLK_UART0, "hclk_uart0", CLK_REF_SYNC_D8, RB(0x34, 0), 60262306a36Sopenharmony_ci RB(0x34, 1), RB(0x34, 2), RB(0x00, 0), 60362306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 60462306a36Sopenharmony_ci D_MODULE(HCLK_UART1, "hclk_uart1", CLK_REF_SYNC_D8, RB(0x34, 3), 60562306a36Sopenharmony_ci RB(0x34, 4), RB(0x34, 5), RB(0x00, 0), 60662306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 60762306a36Sopenharmony_ci D_MODULE(HCLK_UART2, "hclk_uart2", CLK_REF_SYNC_D8, RB(0x34, 6), 60862306a36Sopenharmony_ci RB(0x34, 7), RB(0x34, 8), RB(0x00, 0), 60962306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 61062306a36Sopenharmony_ci D_MODULE(HCLK_UART3, "hclk_uart3", CLK_REF_SYNC_D4, RB(0x40, 24), 61162306a36Sopenharmony_ci RB(0x40, 25), RB(0x40, 26), RB(0x00, 0), 61262306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 61362306a36Sopenharmony_ci D_MODULE(HCLK_UART4, "hclk_uart4", CLK_REF_SYNC_D4, RB(0x40, 27), 61462306a36Sopenharmony_ci RB(0x40, 28), RB(0x40, 29), RB(0x00, 0), 61562306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 61662306a36Sopenharmony_ci D_MODULE(HCLK_UART5, "hclk_uart5", CLK_REF_SYNC_D4, RB(0x44, 0), 61762306a36Sopenharmony_ci RB(0x44, 1), RB(0x44, 2), RB(0x00, 0), 61862306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 61962306a36Sopenharmony_ci D_MODULE(HCLK_UART6, "hclk_uart6", CLK_REF_SYNC_D4, RB(0x44, 3), 62062306a36Sopenharmony_ci RB(0x44, 4), RB(0x44, 5), RB(0x00, 0), 62162306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 62262306a36Sopenharmony_ci D_MODULE(HCLK_UART7, "hclk_uart7", CLK_REF_SYNC_D4, RB(0x44, 6), 62362306a36Sopenharmony_ci RB(0x44, 7), RB(0x44, 8), RB(0x00, 0), 62462306a36Sopenharmony_ci RB(0x00, 0), RB(0x00, 0), RB(0x00, 0)), 62562306a36Sopenharmony_ci /* 62662306a36Sopenharmony_ci * These are not hardware clocks, but are needed to handle the special 62762306a36Sopenharmony_ci * case where we have a 'selector bit' that doesn't just change the 62862306a36Sopenharmony_ci * parent for a clock, but also the gate it's supposed to use. 62962306a36Sopenharmony_ci */ 63062306a36Sopenharmony_ci { 63162306a36Sopenharmony_ci .index = R9A06G032_UART_GROUP_012, 63262306a36Sopenharmony_ci .name = "uart_group_012", 63362306a36Sopenharmony_ci .type = K_BITSEL, 63462306a36Sopenharmony_ci .source = 1 + R9A06G032_DIV_UART, 63562306a36Sopenharmony_ci /* R9A06G032_SYSCTRL_REG_PWRCTRL_PG0_0 */ 63662306a36Sopenharmony_ci .dual.sel = RB(0x34, 30), 63762306a36Sopenharmony_ci .dual.group = 0, 63862306a36Sopenharmony_ci }, 63962306a36Sopenharmony_ci { 64062306a36Sopenharmony_ci .index = R9A06G032_UART_GROUP_34567, 64162306a36Sopenharmony_ci .name = "uart_group_34567", 64262306a36Sopenharmony_ci .type = K_BITSEL, 64362306a36Sopenharmony_ci .source = 1 + R9A06G032_DIV_P2_PG, 64462306a36Sopenharmony_ci /* R9A06G032_SYSCTRL_REG_PWRCTRL_PG1_PR2 */ 64562306a36Sopenharmony_ci .dual.sel = RB(0xec, 24), 64662306a36Sopenharmony_ci .dual.group = 1, 64762306a36Sopenharmony_ci }, 64862306a36Sopenharmony_ci D_UGATE(CLK_UART0, "clk_uart0", UART_GROUP_012, 0, 64962306a36Sopenharmony_ci RB(0x34, 18), RB(0x34, 19), RB(0x34, 20), RB(0x34, 21)), 65062306a36Sopenharmony_ci D_UGATE(CLK_UART1, "clk_uart1", UART_GROUP_012, 0, 65162306a36Sopenharmony_ci RB(0x34, 22), RB(0x34, 23), RB(0x34, 24), RB(0x34, 25)), 65262306a36Sopenharmony_ci D_UGATE(CLK_UART2, "clk_uart2", UART_GROUP_012, 0, 65362306a36Sopenharmony_ci RB(0x34, 26), RB(0x34, 27), RB(0x34, 28), RB(0x34, 29)), 65462306a36Sopenharmony_ci D_UGATE(CLK_UART3, "clk_uart3", UART_GROUP_34567, 1, 65562306a36Sopenharmony_ci RB(0xec, 0), RB(0xec, 1), RB(0xec, 2), RB(0xec, 3)), 65662306a36Sopenharmony_ci D_UGATE(CLK_UART4, "clk_uart4", UART_GROUP_34567, 1, 65762306a36Sopenharmony_ci RB(0xec, 4), RB(0xec, 5), RB(0xec, 6), RB(0xec, 7)), 65862306a36Sopenharmony_ci D_UGATE(CLK_UART5, "clk_uart5", UART_GROUP_34567, 1, 65962306a36Sopenharmony_ci RB(0xec, 8), RB(0xec, 9), RB(0xec, 10), RB(0xec, 11)), 66062306a36Sopenharmony_ci D_UGATE(CLK_UART6, "clk_uart6", UART_GROUP_34567, 1, 66162306a36Sopenharmony_ci RB(0xec, 12), RB(0xec, 13), RB(0xec, 14), RB(0xec, 15)), 66262306a36Sopenharmony_ci D_UGATE(CLK_UART7, "clk_uart7", UART_GROUP_34567, 1, 66362306a36Sopenharmony_ci RB(0xec, 16), RB(0xec, 17), RB(0xec, 18), RB(0xec, 19)), 66462306a36Sopenharmony_ci}; 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_cistruct r9a06g032_priv { 66762306a36Sopenharmony_ci struct clk_onecell_data data; 66862306a36Sopenharmony_ci spinlock_t lock; /* protects concurrent access to gates */ 66962306a36Sopenharmony_ci void __iomem *reg; 67062306a36Sopenharmony_ci}; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_cistatic struct r9a06g032_priv *sysctrl_priv; 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci/* Exported helper to access the DMAMUX register */ 67562306a36Sopenharmony_ciint r9a06g032_sysctrl_set_dmamux(u32 mask, u32 val) 67662306a36Sopenharmony_ci{ 67762306a36Sopenharmony_ci unsigned long flags; 67862306a36Sopenharmony_ci u32 dmamux; 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci if (!sysctrl_priv) 68162306a36Sopenharmony_ci return -EPROBE_DEFER; 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci spin_lock_irqsave(&sysctrl_priv->lock, flags); 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci dmamux = readl(sysctrl_priv->reg + R9A06G032_SYSCTRL_DMAMUX); 68662306a36Sopenharmony_ci dmamux &= ~mask; 68762306a36Sopenharmony_ci dmamux |= val & mask; 68862306a36Sopenharmony_ci writel(dmamux, sysctrl_priv->reg + R9A06G032_SYSCTRL_DMAMUX); 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci spin_unlock_irqrestore(&sysctrl_priv->lock, flags); 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci return 0; 69362306a36Sopenharmony_ci} 69462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(r9a06g032_sysctrl_set_dmamux); 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_cistatic void clk_rdesc_set(struct r9a06g032_priv *clocks, 69762306a36Sopenharmony_ci struct regbit rb, unsigned int on) 69862306a36Sopenharmony_ci{ 69962306a36Sopenharmony_ci u32 __iomem *reg = clocks->reg + (rb.reg * 4); 70062306a36Sopenharmony_ci u32 val; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci if (!rb.reg && !rb.bit) 70362306a36Sopenharmony_ci return; 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci val = readl(reg); 70662306a36Sopenharmony_ci val = (val & ~BIT(rb.bit)) | ((!!on) << rb.bit); 70762306a36Sopenharmony_ci writel(val, reg); 70862306a36Sopenharmony_ci} 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_cistatic int clk_rdesc_get(struct r9a06g032_priv *clocks, struct regbit rb) 71162306a36Sopenharmony_ci{ 71262306a36Sopenharmony_ci u32 __iomem *reg = clocks->reg + (rb.reg * 4); 71362306a36Sopenharmony_ci u32 val = readl(reg); 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci return !!(val & BIT(rb.bit)); 71662306a36Sopenharmony_ci} 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci/* 71962306a36Sopenharmony_ci * This implements the R9A06G032 clock gate 'driver'. We cannot use the system's 72062306a36Sopenharmony_ci * clock gate framework as the gates on the R9A06G032 have a special enabling 72162306a36Sopenharmony_ci * sequence, therefore we use this little proxy. 72262306a36Sopenharmony_ci */ 72362306a36Sopenharmony_cistruct r9a06g032_clk_gate { 72462306a36Sopenharmony_ci struct clk_hw hw; 72562306a36Sopenharmony_ci struct r9a06g032_priv *clocks; 72662306a36Sopenharmony_ci u16 index; 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci struct r9a06g032_gate gate; 72962306a36Sopenharmony_ci}; 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci#define to_r9a06g032_gate(_hw) container_of(_hw, struct r9a06g032_clk_gate, hw) 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_cistatic int create_add_module_clock(struct of_phandle_args *clkspec, 73462306a36Sopenharmony_ci struct device *dev) 73562306a36Sopenharmony_ci{ 73662306a36Sopenharmony_ci struct clk *clk; 73762306a36Sopenharmony_ci int error; 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci clk = of_clk_get_from_provider(clkspec); 74062306a36Sopenharmony_ci if (IS_ERR(clk)) 74162306a36Sopenharmony_ci return PTR_ERR(clk); 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci error = pm_clk_create(dev); 74462306a36Sopenharmony_ci if (error) { 74562306a36Sopenharmony_ci clk_put(clk); 74662306a36Sopenharmony_ci return error; 74762306a36Sopenharmony_ci } 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci error = pm_clk_add_clk(dev, clk); 75062306a36Sopenharmony_ci if (error) { 75162306a36Sopenharmony_ci pm_clk_destroy(dev); 75262306a36Sopenharmony_ci clk_put(clk); 75362306a36Sopenharmony_ci } 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci return error; 75662306a36Sopenharmony_ci} 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_cistatic int r9a06g032_attach_dev(struct generic_pm_domain *pd, 75962306a36Sopenharmony_ci struct device *dev) 76062306a36Sopenharmony_ci{ 76162306a36Sopenharmony_ci struct device_node *np = dev->of_node; 76262306a36Sopenharmony_ci struct of_phandle_args clkspec; 76362306a36Sopenharmony_ci int i = 0; 76462306a36Sopenharmony_ci int error; 76562306a36Sopenharmony_ci int index; 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i++, 76862306a36Sopenharmony_ci &clkspec)) { 76962306a36Sopenharmony_ci if (clkspec.np != pd->dev.of_node) 77062306a36Sopenharmony_ci continue; 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci index = clkspec.args[0]; 77362306a36Sopenharmony_ci if (index < R9A06G032_CLOCK_COUNT && 77462306a36Sopenharmony_ci r9a06g032_clocks[index].managed) { 77562306a36Sopenharmony_ci error = create_add_module_clock(&clkspec, dev); 77662306a36Sopenharmony_ci of_node_put(clkspec.np); 77762306a36Sopenharmony_ci if (error) 77862306a36Sopenharmony_ci return error; 77962306a36Sopenharmony_ci } 78062306a36Sopenharmony_ci } 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci return 0; 78362306a36Sopenharmony_ci} 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_cistatic void r9a06g032_detach_dev(struct generic_pm_domain *unused, struct device *dev) 78662306a36Sopenharmony_ci{ 78762306a36Sopenharmony_ci if (!pm_clk_no_clocks(dev)) 78862306a36Sopenharmony_ci pm_clk_destroy(dev); 78962306a36Sopenharmony_ci} 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_cistatic int r9a06g032_add_clk_domain(struct device *dev) 79262306a36Sopenharmony_ci{ 79362306a36Sopenharmony_ci struct device_node *np = dev->of_node; 79462306a36Sopenharmony_ci struct generic_pm_domain *pd; 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); 79762306a36Sopenharmony_ci if (!pd) 79862306a36Sopenharmony_ci return -ENOMEM; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci pd->name = np->name; 80162306a36Sopenharmony_ci pd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ALWAYS_ON | 80262306a36Sopenharmony_ci GENPD_FLAG_ACTIVE_WAKEUP; 80362306a36Sopenharmony_ci pd->attach_dev = r9a06g032_attach_dev; 80462306a36Sopenharmony_ci pd->detach_dev = r9a06g032_detach_dev; 80562306a36Sopenharmony_ci pm_genpd_init(pd, &pm_domain_always_on_gov, false); 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci of_genpd_add_provider_simple(np, pd); 80862306a36Sopenharmony_ci return 0; 80962306a36Sopenharmony_ci} 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_cistatic void 81262306a36Sopenharmony_cir9a06g032_clk_gate_set(struct r9a06g032_priv *clocks, 81362306a36Sopenharmony_ci struct r9a06g032_gate *g, int on) 81462306a36Sopenharmony_ci{ 81562306a36Sopenharmony_ci unsigned long flags; 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci WARN_ON(!g->gate.reg && !g->gate.bit); 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci spin_lock_irqsave(&clocks->lock, flags); 82062306a36Sopenharmony_ci clk_rdesc_set(clocks, g->gate, on); 82162306a36Sopenharmony_ci /* De-assert reset */ 82262306a36Sopenharmony_ci clk_rdesc_set(clocks, g->reset, 1); 82362306a36Sopenharmony_ci spin_unlock_irqrestore(&clocks->lock, flags); 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci /* Hardware manual recommends 5us delay after enabling clock & reset */ 82662306a36Sopenharmony_ci udelay(5); 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci /* If the peripheral is memory mapped (i.e. an AXI slave), there is an 82962306a36Sopenharmony_ci * associated SLVRDY bit in the System Controller that needs to be set 83062306a36Sopenharmony_ci * so that the FlexWAY bus fabric passes on the read/write requests. 83162306a36Sopenharmony_ci */ 83262306a36Sopenharmony_ci spin_lock_irqsave(&clocks->lock, flags); 83362306a36Sopenharmony_ci clk_rdesc_set(clocks, g->ready, on); 83462306a36Sopenharmony_ci /* Clear 'Master Idle Request' bit */ 83562306a36Sopenharmony_ci clk_rdesc_set(clocks, g->midle, !on); 83662306a36Sopenharmony_ci spin_unlock_irqrestore(&clocks->lock, flags); 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci /* Note: We don't wait for FlexWAY Socket Connection signal */ 83962306a36Sopenharmony_ci} 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_cistatic int r9a06g032_clk_gate_enable(struct clk_hw *hw) 84262306a36Sopenharmony_ci{ 84362306a36Sopenharmony_ci struct r9a06g032_clk_gate *g = to_r9a06g032_gate(hw); 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci r9a06g032_clk_gate_set(g->clocks, &g->gate, 1); 84662306a36Sopenharmony_ci return 0; 84762306a36Sopenharmony_ci} 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_cistatic void r9a06g032_clk_gate_disable(struct clk_hw *hw) 85062306a36Sopenharmony_ci{ 85162306a36Sopenharmony_ci struct r9a06g032_clk_gate *g = to_r9a06g032_gate(hw); 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci r9a06g032_clk_gate_set(g->clocks, &g->gate, 0); 85462306a36Sopenharmony_ci} 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_cistatic int r9a06g032_clk_gate_is_enabled(struct clk_hw *hw) 85762306a36Sopenharmony_ci{ 85862306a36Sopenharmony_ci struct r9a06g032_clk_gate *g = to_r9a06g032_gate(hw); 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci /* if clock is in reset, the gate might be on, and still not 'be' on */ 86162306a36Sopenharmony_ci if (g->gate.reset.reg && !clk_rdesc_get(g->clocks, g->gate.reset)) 86262306a36Sopenharmony_ci return 0; 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci return clk_rdesc_get(g->clocks, g->gate.gate); 86562306a36Sopenharmony_ci} 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_cistatic const struct clk_ops r9a06g032_clk_gate_ops = { 86862306a36Sopenharmony_ci .enable = r9a06g032_clk_gate_enable, 86962306a36Sopenharmony_ci .disable = r9a06g032_clk_gate_disable, 87062306a36Sopenharmony_ci .is_enabled = r9a06g032_clk_gate_is_enabled, 87162306a36Sopenharmony_ci}; 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_cistatic struct clk * 87462306a36Sopenharmony_cir9a06g032_register_gate(struct r9a06g032_priv *clocks, 87562306a36Sopenharmony_ci const char *parent_name, 87662306a36Sopenharmony_ci const struct r9a06g032_clkdesc *desc) 87762306a36Sopenharmony_ci{ 87862306a36Sopenharmony_ci struct clk *clk; 87962306a36Sopenharmony_ci struct r9a06g032_clk_gate *g; 88062306a36Sopenharmony_ci struct clk_init_data init = {}; 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci g = kzalloc(sizeof(*g), GFP_KERNEL); 88362306a36Sopenharmony_ci if (!g) 88462306a36Sopenharmony_ci return NULL; 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci init.name = desc->name; 88762306a36Sopenharmony_ci init.ops = &r9a06g032_clk_gate_ops; 88862306a36Sopenharmony_ci init.flags = CLK_SET_RATE_PARENT; 88962306a36Sopenharmony_ci init.parent_names = parent_name ? &parent_name : NULL; 89062306a36Sopenharmony_ci init.num_parents = parent_name ? 1 : 0; 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci g->clocks = clocks; 89362306a36Sopenharmony_ci g->index = desc->index; 89462306a36Sopenharmony_ci g->gate = desc->gate; 89562306a36Sopenharmony_ci g->hw.init = &init; 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci /* 89862306a36Sopenharmony_ci * important here, some clocks are already in use by the CM3, we 89962306a36Sopenharmony_ci * have to assume they are not Linux's to play with and try to disable 90062306a36Sopenharmony_ci * at the end of the boot! 90162306a36Sopenharmony_ci */ 90262306a36Sopenharmony_ci if (r9a06g032_clk_gate_is_enabled(&g->hw)) { 90362306a36Sopenharmony_ci init.flags |= CLK_IS_CRITICAL; 90462306a36Sopenharmony_ci pr_debug("%s was enabled, making read-only\n", desc->name); 90562306a36Sopenharmony_ci } 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci clk = clk_register(NULL, &g->hw); 90862306a36Sopenharmony_ci if (IS_ERR(clk)) { 90962306a36Sopenharmony_ci kfree(g); 91062306a36Sopenharmony_ci return NULL; 91162306a36Sopenharmony_ci } 91262306a36Sopenharmony_ci return clk; 91362306a36Sopenharmony_ci} 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_cistruct r9a06g032_clk_div { 91662306a36Sopenharmony_ci struct clk_hw hw; 91762306a36Sopenharmony_ci struct r9a06g032_priv *clocks; 91862306a36Sopenharmony_ci u16 index; 91962306a36Sopenharmony_ci u16 reg; 92062306a36Sopenharmony_ci u16 min, max; 92162306a36Sopenharmony_ci u8 table_size; 92262306a36Sopenharmony_ci u16 table[8]; /* we know there are no more than 8 */ 92362306a36Sopenharmony_ci}; 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci#define to_r9a06g032_div(_hw) \ 92662306a36Sopenharmony_ci container_of(_hw, struct r9a06g032_clk_div, hw) 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_cistatic unsigned long 92962306a36Sopenharmony_cir9a06g032_div_recalc_rate(struct clk_hw *hw, 93062306a36Sopenharmony_ci unsigned long parent_rate) 93162306a36Sopenharmony_ci{ 93262306a36Sopenharmony_ci struct r9a06g032_clk_div *clk = to_r9a06g032_div(hw); 93362306a36Sopenharmony_ci u32 __iomem *reg = clk->clocks->reg + (4 * clk->reg); 93462306a36Sopenharmony_ci u32 div = readl(reg); 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci if (div < clk->min) 93762306a36Sopenharmony_ci div = clk->min; 93862306a36Sopenharmony_ci else if (div > clk->max) 93962306a36Sopenharmony_ci div = clk->max; 94062306a36Sopenharmony_ci return DIV_ROUND_UP(parent_rate, div); 94162306a36Sopenharmony_ci} 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci/* 94462306a36Sopenharmony_ci * Attempts to find a value that is in range of min,max, 94562306a36Sopenharmony_ci * and if a table of set dividers was specified for this 94662306a36Sopenharmony_ci * register, try to find the fixed divider that is the closest 94762306a36Sopenharmony_ci * to the target frequency 94862306a36Sopenharmony_ci */ 94962306a36Sopenharmony_cistatic long 95062306a36Sopenharmony_cir9a06g032_div_clamp_div(struct r9a06g032_clk_div *clk, 95162306a36Sopenharmony_ci unsigned long rate, unsigned long prate) 95262306a36Sopenharmony_ci{ 95362306a36Sopenharmony_ci /* + 1 to cope with rates that have the remainder dropped */ 95462306a36Sopenharmony_ci u32 div = DIV_ROUND_UP(prate, rate + 1); 95562306a36Sopenharmony_ci int i; 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci if (div <= clk->min) 95862306a36Sopenharmony_ci return clk->min; 95962306a36Sopenharmony_ci if (div >= clk->max) 96062306a36Sopenharmony_ci return clk->max; 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci for (i = 0; clk->table_size && i < clk->table_size - 1; i++) { 96362306a36Sopenharmony_ci if (div >= clk->table[i] && div <= clk->table[i + 1]) { 96462306a36Sopenharmony_ci unsigned long m = rate - 96562306a36Sopenharmony_ci DIV_ROUND_UP(prate, clk->table[i]); 96662306a36Sopenharmony_ci unsigned long p = 96762306a36Sopenharmony_ci DIV_ROUND_UP(prate, clk->table[i + 1]) - 96862306a36Sopenharmony_ci rate; 96962306a36Sopenharmony_ci /* 97062306a36Sopenharmony_ci * select the divider that generates 97162306a36Sopenharmony_ci * the value closest to the ideal frequency 97262306a36Sopenharmony_ci */ 97362306a36Sopenharmony_ci div = p >= m ? clk->table[i] : clk->table[i + 1]; 97462306a36Sopenharmony_ci return div; 97562306a36Sopenharmony_ci } 97662306a36Sopenharmony_ci } 97762306a36Sopenharmony_ci return div; 97862306a36Sopenharmony_ci} 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_cistatic int 98162306a36Sopenharmony_cir9a06g032_div_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) 98262306a36Sopenharmony_ci{ 98362306a36Sopenharmony_ci struct r9a06g032_clk_div *clk = to_r9a06g032_div(hw); 98462306a36Sopenharmony_ci u32 div = DIV_ROUND_UP(req->best_parent_rate, req->rate); 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci pr_devel("%s %pC %ld (prate %ld) (wanted div %u)\n", __func__, 98762306a36Sopenharmony_ci hw->clk, req->rate, req->best_parent_rate, div); 98862306a36Sopenharmony_ci pr_devel(" min %d (%ld) max %d (%ld)\n", 98962306a36Sopenharmony_ci clk->min, DIV_ROUND_UP(req->best_parent_rate, clk->min), 99062306a36Sopenharmony_ci clk->max, DIV_ROUND_UP(req->best_parent_rate, clk->max)); 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci div = r9a06g032_div_clamp_div(clk, req->rate, req->best_parent_rate); 99362306a36Sopenharmony_ci /* 99462306a36Sopenharmony_ci * this is a hack. Currently the serial driver asks for a clock rate 99562306a36Sopenharmony_ci * that is 16 times the baud rate -- and that is wildly outside the 99662306a36Sopenharmony_ci * range of the UART divider, somehow there is no provision for that 99762306a36Sopenharmony_ci * case of 'let the divider as is if outside range'. 99862306a36Sopenharmony_ci * The serial driver *shouldn't* play with these clocks anyway, there's 99962306a36Sopenharmony_ci * several uarts attached to this divider, and changing this impacts 100062306a36Sopenharmony_ci * everyone. 100162306a36Sopenharmony_ci */ 100262306a36Sopenharmony_ci if (clk->index == R9A06G032_DIV_UART || 100362306a36Sopenharmony_ci clk->index == R9A06G032_DIV_P2_PG) { 100462306a36Sopenharmony_ci pr_devel("%s div uart hack!\n", __func__); 100562306a36Sopenharmony_ci req->rate = clk_get_rate(hw->clk); 100662306a36Sopenharmony_ci return 0; 100762306a36Sopenharmony_ci } 100862306a36Sopenharmony_ci req->rate = DIV_ROUND_UP(req->best_parent_rate, div); 100962306a36Sopenharmony_ci pr_devel("%s %pC %ld / %u = %ld\n", __func__, hw->clk, 101062306a36Sopenharmony_ci req->best_parent_rate, div, req->rate); 101162306a36Sopenharmony_ci return 0; 101262306a36Sopenharmony_ci} 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_cistatic int 101562306a36Sopenharmony_cir9a06g032_div_set_rate(struct clk_hw *hw, 101662306a36Sopenharmony_ci unsigned long rate, unsigned long parent_rate) 101762306a36Sopenharmony_ci{ 101862306a36Sopenharmony_ci struct r9a06g032_clk_div *clk = to_r9a06g032_div(hw); 101962306a36Sopenharmony_ci /* + 1 to cope with rates that have the remainder dropped */ 102062306a36Sopenharmony_ci u32 div = DIV_ROUND_UP(parent_rate, rate + 1); 102162306a36Sopenharmony_ci u32 __iomem *reg = clk->clocks->reg + (4 * clk->reg); 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci pr_devel("%s %pC rate %ld parent %ld div %d\n", __func__, hw->clk, 102462306a36Sopenharmony_ci rate, parent_rate, div); 102562306a36Sopenharmony_ci 102662306a36Sopenharmony_ci /* 102762306a36Sopenharmony_ci * Need to write the bit 31 with the divider value to 102862306a36Sopenharmony_ci * latch it. Technically we should wait until it has been 102962306a36Sopenharmony_ci * cleared too. 103062306a36Sopenharmony_ci * TODO: Find whether this callback is sleepable, in case 103162306a36Sopenharmony_ci * the hardware /does/ require some sort of spinloop here. 103262306a36Sopenharmony_ci */ 103362306a36Sopenharmony_ci writel(div | BIT(31), reg); 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci return 0; 103662306a36Sopenharmony_ci} 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_cistatic const struct clk_ops r9a06g032_clk_div_ops = { 103962306a36Sopenharmony_ci .recalc_rate = r9a06g032_div_recalc_rate, 104062306a36Sopenharmony_ci .determine_rate = r9a06g032_div_determine_rate, 104162306a36Sopenharmony_ci .set_rate = r9a06g032_div_set_rate, 104262306a36Sopenharmony_ci}; 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_cistatic struct clk * 104562306a36Sopenharmony_cir9a06g032_register_div(struct r9a06g032_priv *clocks, 104662306a36Sopenharmony_ci const char *parent_name, 104762306a36Sopenharmony_ci const struct r9a06g032_clkdesc *desc) 104862306a36Sopenharmony_ci{ 104962306a36Sopenharmony_ci struct r9a06g032_clk_div *div; 105062306a36Sopenharmony_ci struct clk *clk; 105162306a36Sopenharmony_ci struct clk_init_data init = {}; 105262306a36Sopenharmony_ci unsigned int i; 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci div = kzalloc(sizeof(*div), GFP_KERNEL); 105562306a36Sopenharmony_ci if (!div) 105662306a36Sopenharmony_ci return NULL; 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_ci init.name = desc->name; 105962306a36Sopenharmony_ci init.ops = &r9a06g032_clk_div_ops; 106062306a36Sopenharmony_ci init.flags = CLK_SET_RATE_PARENT; 106162306a36Sopenharmony_ci init.parent_names = parent_name ? &parent_name : NULL; 106262306a36Sopenharmony_ci init.num_parents = parent_name ? 1 : 0; 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_ci div->clocks = clocks; 106562306a36Sopenharmony_ci div->index = desc->index; 106662306a36Sopenharmony_ci div->reg = desc->reg; 106762306a36Sopenharmony_ci div->hw.init = &init; 106862306a36Sopenharmony_ci div->min = desc->div_min; 106962306a36Sopenharmony_ci div->max = desc->div_max; 107062306a36Sopenharmony_ci /* populate (optional) divider table fixed values */ 107162306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(div->table) && 107262306a36Sopenharmony_ci i < ARRAY_SIZE(desc->div_table) && desc->div_table[i]; i++) { 107362306a36Sopenharmony_ci div->table[div->table_size++] = desc->div_table[i]; 107462306a36Sopenharmony_ci } 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci clk = clk_register(NULL, &div->hw); 107762306a36Sopenharmony_ci if (IS_ERR(clk)) { 107862306a36Sopenharmony_ci kfree(div); 107962306a36Sopenharmony_ci return NULL; 108062306a36Sopenharmony_ci } 108162306a36Sopenharmony_ci return clk; 108262306a36Sopenharmony_ci} 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci/* 108562306a36Sopenharmony_ci * This clock provider handles the case of the R9A06G032 where you have 108662306a36Sopenharmony_ci * peripherals that have two potential clock source and two gates, one for 108762306a36Sopenharmony_ci * each of the clock source - the used clock source (for all sub clocks) 108862306a36Sopenharmony_ci * is selected by a single bit. 108962306a36Sopenharmony_ci * That single bit affects all sub-clocks, and therefore needs to change the 109062306a36Sopenharmony_ci * active gate (and turn the others off) and force a recalculation of the rates. 109162306a36Sopenharmony_ci * 109262306a36Sopenharmony_ci * This implements two clock providers, one 'bitselect' that 109362306a36Sopenharmony_ci * handles the switch between both parents, and another 'dualgate' 109462306a36Sopenharmony_ci * that knows which gate to poke at, depending on the parent's bit position. 109562306a36Sopenharmony_ci */ 109662306a36Sopenharmony_cistruct r9a06g032_clk_bitsel { 109762306a36Sopenharmony_ci struct clk_hw hw; 109862306a36Sopenharmony_ci struct r9a06g032_priv *clocks; 109962306a36Sopenharmony_ci u16 index; 110062306a36Sopenharmony_ci struct regbit selector; /* selector register + bit */ 110162306a36Sopenharmony_ci}; 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci#define to_clk_bitselect(_hw) \ 110462306a36Sopenharmony_ci container_of(_hw, struct r9a06g032_clk_bitsel, hw) 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_cistatic u8 r9a06g032_clk_mux_get_parent(struct clk_hw *hw) 110762306a36Sopenharmony_ci{ 110862306a36Sopenharmony_ci struct r9a06g032_clk_bitsel *set = to_clk_bitselect(hw); 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci return clk_rdesc_get(set->clocks, set->selector); 111162306a36Sopenharmony_ci} 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_cistatic int r9a06g032_clk_mux_set_parent(struct clk_hw *hw, u8 index) 111462306a36Sopenharmony_ci{ 111562306a36Sopenharmony_ci struct r9a06g032_clk_bitsel *set = to_clk_bitselect(hw); 111662306a36Sopenharmony_ci 111762306a36Sopenharmony_ci /* a single bit in the register selects one of two parent clocks */ 111862306a36Sopenharmony_ci clk_rdesc_set(set->clocks, set->selector, !!index); 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci return 0; 112162306a36Sopenharmony_ci} 112262306a36Sopenharmony_ci 112362306a36Sopenharmony_cistatic const struct clk_ops clk_bitselect_ops = { 112462306a36Sopenharmony_ci .determine_rate = clk_hw_determine_rate_no_reparent, 112562306a36Sopenharmony_ci .get_parent = r9a06g032_clk_mux_get_parent, 112662306a36Sopenharmony_ci .set_parent = r9a06g032_clk_mux_set_parent, 112762306a36Sopenharmony_ci}; 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_cistatic struct clk * 113062306a36Sopenharmony_cir9a06g032_register_bitsel(struct r9a06g032_priv *clocks, 113162306a36Sopenharmony_ci const char *parent_name, 113262306a36Sopenharmony_ci const struct r9a06g032_clkdesc *desc) 113362306a36Sopenharmony_ci{ 113462306a36Sopenharmony_ci struct clk *clk; 113562306a36Sopenharmony_ci struct r9a06g032_clk_bitsel *g; 113662306a36Sopenharmony_ci struct clk_init_data init = {}; 113762306a36Sopenharmony_ci const char *names[2]; 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_ci /* allocate the gate */ 114062306a36Sopenharmony_ci g = kzalloc(sizeof(*g), GFP_KERNEL); 114162306a36Sopenharmony_ci if (!g) 114262306a36Sopenharmony_ci return NULL; 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci names[0] = parent_name; 114562306a36Sopenharmony_ci names[1] = "clk_pll_usb"; 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci init.name = desc->name; 114862306a36Sopenharmony_ci init.ops = &clk_bitselect_ops; 114962306a36Sopenharmony_ci init.flags = CLK_SET_RATE_PARENT; 115062306a36Sopenharmony_ci init.parent_names = names; 115162306a36Sopenharmony_ci init.num_parents = 2; 115262306a36Sopenharmony_ci 115362306a36Sopenharmony_ci g->clocks = clocks; 115462306a36Sopenharmony_ci g->index = desc->index; 115562306a36Sopenharmony_ci g->selector = desc->dual.sel; 115662306a36Sopenharmony_ci g->hw.init = &init; 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci clk = clk_register(NULL, &g->hw); 115962306a36Sopenharmony_ci if (IS_ERR(clk)) { 116062306a36Sopenharmony_ci kfree(g); 116162306a36Sopenharmony_ci return NULL; 116262306a36Sopenharmony_ci } 116362306a36Sopenharmony_ci return clk; 116462306a36Sopenharmony_ci} 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_cistruct r9a06g032_clk_dualgate { 116762306a36Sopenharmony_ci struct clk_hw hw; 116862306a36Sopenharmony_ci struct r9a06g032_priv *clocks; 116962306a36Sopenharmony_ci u16 index; 117062306a36Sopenharmony_ci struct regbit selector; /* selector register + bit */ 117162306a36Sopenharmony_ci struct r9a06g032_gate gate[2]; 117262306a36Sopenharmony_ci}; 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_ci#define to_clk_dualgate(_hw) \ 117562306a36Sopenharmony_ci container_of(_hw, struct r9a06g032_clk_dualgate, hw) 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_cistatic int 117862306a36Sopenharmony_cir9a06g032_clk_dualgate_setenable(struct r9a06g032_clk_dualgate *g, int enable) 117962306a36Sopenharmony_ci{ 118062306a36Sopenharmony_ci u8 sel_bit = clk_rdesc_get(g->clocks, g->selector); 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci /* we always turn off the 'other' gate, regardless */ 118362306a36Sopenharmony_ci r9a06g032_clk_gate_set(g->clocks, &g->gate[!sel_bit], 0); 118462306a36Sopenharmony_ci r9a06g032_clk_gate_set(g->clocks, &g->gate[sel_bit], enable); 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci return 0; 118762306a36Sopenharmony_ci} 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_cistatic int r9a06g032_clk_dualgate_enable(struct clk_hw *hw) 119062306a36Sopenharmony_ci{ 119162306a36Sopenharmony_ci struct r9a06g032_clk_dualgate *gate = to_clk_dualgate(hw); 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_ci r9a06g032_clk_dualgate_setenable(gate, 1); 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_ci return 0; 119662306a36Sopenharmony_ci} 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_cistatic void r9a06g032_clk_dualgate_disable(struct clk_hw *hw) 119962306a36Sopenharmony_ci{ 120062306a36Sopenharmony_ci struct r9a06g032_clk_dualgate *gate = to_clk_dualgate(hw); 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ci r9a06g032_clk_dualgate_setenable(gate, 0); 120362306a36Sopenharmony_ci} 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_cistatic int r9a06g032_clk_dualgate_is_enabled(struct clk_hw *hw) 120662306a36Sopenharmony_ci{ 120762306a36Sopenharmony_ci struct r9a06g032_clk_dualgate *g = to_clk_dualgate(hw); 120862306a36Sopenharmony_ci u8 sel_bit = clk_rdesc_get(g->clocks, g->selector); 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci return clk_rdesc_get(g->clocks, g->gate[sel_bit].gate); 121162306a36Sopenharmony_ci} 121262306a36Sopenharmony_ci 121362306a36Sopenharmony_cistatic const struct clk_ops r9a06g032_clk_dualgate_ops = { 121462306a36Sopenharmony_ci .enable = r9a06g032_clk_dualgate_enable, 121562306a36Sopenharmony_ci .disable = r9a06g032_clk_dualgate_disable, 121662306a36Sopenharmony_ci .is_enabled = r9a06g032_clk_dualgate_is_enabled, 121762306a36Sopenharmony_ci}; 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_cistatic struct clk * 122062306a36Sopenharmony_cir9a06g032_register_dualgate(struct r9a06g032_priv *clocks, 122162306a36Sopenharmony_ci const char *parent_name, 122262306a36Sopenharmony_ci const struct r9a06g032_clkdesc *desc, 122362306a36Sopenharmony_ci struct regbit sel) 122462306a36Sopenharmony_ci{ 122562306a36Sopenharmony_ci struct r9a06g032_clk_dualgate *g; 122662306a36Sopenharmony_ci struct clk *clk; 122762306a36Sopenharmony_ci struct clk_init_data init = {}; 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci /* allocate the gate */ 123062306a36Sopenharmony_ci g = kzalloc(sizeof(*g), GFP_KERNEL); 123162306a36Sopenharmony_ci if (!g) 123262306a36Sopenharmony_ci return NULL; 123362306a36Sopenharmony_ci g->clocks = clocks; 123462306a36Sopenharmony_ci g->index = desc->index; 123562306a36Sopenharmony_ci g->selector = sel; 123662306a36Sopenharmony_ci g->gate[0].gate = desc->dual.g1; 123762306a36Sopenharmony_ci g->gate[0].reset = desc->dual.r1; 123862306a36Sopenharmony_ci g->gate[1].gate = desc->dual.g2; 123962306a36Sopenharmony_ci g->gate[1].reset = desc->dual.r2; 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci init.name = desc->name; 124262306a36Sopenharmony_ci init.ops = &r9a06g032_clk_dualgate_ops; 124362306a36Sopenharmony_ci init.flags = CLK_SET_RATE_PARENT; 124462306a36Sopenharmony_ci init.parent_names = &parent_name; 124562306a36Sopenharmony_ci init.num_parents = 1; 124662306a36Sopenharmony_ci g->hw.init = &init; 124762306a36Sopenharmony_ci /* 124862306a36Sopenharmony_ci * important here, some clocks are already in use by the CM3, we 124962306a36Sopenharmony_ci * have to assume they are not Linux's to play with and try to disable 125062306a36Sopenharmony_ci * at the end of the boot! 125162306a36Sopenharmony_ci */ 125262306a36Sopenharmony_ci if (r9a06g032_clk_dualgate_is_enabled(&g->hw)) { 125362306a36Sopenharmony_ci init.flags |= CLK_IS_CRITICAL; 125462306a36Sopenharmony_ci pr_debug("%s was enabled, making read-only\n", desc->name); 125562306a36Sopenharmony_ci } 125662306a36Sopenharmony_ci 125762306a36Sopenharmony_ci clk = clk_register(NULL, &g->hw); 125862306a36Sopenharmony_ci if (IS_ERR(clk)) { 125962306a36Sopenharmony_ci kfree(g); 126062306a36Sopenharmony_ci return NULL; 126162306a36Sopenharmony_ci } 126262306a36Sopenharmony_ci return clk; 126362306a36Sopenharmony_ci} 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_cistatic void r9a06g032_clocks_del_clk_provider(void *data) 126662306a36Sopenharmony_ci{ 126762306a36Sopenharmony_ci of_clk_del_provider(data); 126862306a36Sopenharmony_ci} 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_cistatic void __init r9a06g032_init_h2mode(struct r9a06g032_priv *clocks) 127162306a36Sopenharmony_ci{ 127262306a36Sopenharmony_ci struct device_node *usbf_np = NULL; 127362306a36Sopenharmony_ci u32 usb; 127462306a36Sopenharmony_ci 127562306a36Sopenharmony_ci while ((usbf_np = of_find_compatible_node(usbf_np, NULL, 127662306a36Sopenharmony_ci "renesas,rzn1-usbf"))) { 127762306a36Sopenharmony_ci if (of_device_is_available(usbf_np)) 127862306a36Sopenharmony_ci break; 127962306a36Sopenharmony_ci } 128062306a36Sopenharmony_ci 128162306a36Sopenharmony_ci usb = readl(clocks->reg + R9A06G032_SYSCTRL_USB); 128262306a36Sopenharmony_ci if (usbf_np) { 128362306a36Sopenharmony_ci /* 1 host and 1 device mode */ 128462306a36Sopenharmony_ci usb &= ~R9A06G032_SYSCTRL_USB_H2MODE; 128562306a36Sopenharmony_ci of_node_put(usbf_np); 128662306a36Sopenharmony_ci } else { 128762306a36Sopenharmony_ci /* 2 hosts mode */ 128862306a36Sopenharmony_ci usb |= R9A06G032_SYSCTRL_USB_H2MODE; 128962306a36Sopenharmony_ci } 129062306a36Sopenharmony_ci writel(usb, clocks->reg + R9A06G032_SYSCTRL_USB); 129162306a36Sopenharmony_ci} 129262306a36Sopenharmony_ci 129362306a36Sopenharmony_cistatic int __init r9a06g032_clocks_probe(struct platform_device *pdev) 129462306a36Sopenharmony_ci{ 129562306a36Sopenharmony_ci struct device *dev = &pdev->dev; 129662306a36Sopenharmony_ci struct device_node *np = dev->of_node; 129762306a36Sopenharmony_ci struct r9a06g032_priv *clocks; 129862306a36Sopenharmony_ci struct clk **clks; 129962306a36Sopenharmony_ci struct clk *mclk; 130062306a36Sopenharmony_ci unsigned int i; 130162306a36Sopenharmony_ci struct regbit uart_group_sel[2]; 130262306a36Sopenharmony_ci int error; 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_ci clocks = devm_kzalloc(dev, sizeof(*clocks), GFP_KERNEL); 130562306a36Sopenharmony_ci clks = devm_kcalloc(dev, R9A06G032_CLOCK_COUNT, sizeof(struct clk *), 130662306a36Sopenharmony_ci GFP_KERNEL); 130762306a36Sopenharmony_ci if (!clocks || !clks) 130862306a36Sopenharmony_ci return -ENOMEM; 130962306a36Sopenharmony_ci 131062306a36Sopenharmony_ci spin_lock_init(&clocks->lock); 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci clocks->data.clks = clks; 131362306a36Sopenharmony_ci clocks->data.clk_num = R9A06G032_CLOCK_COUNT; 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_ci mclk = devm_clk_get(dev, "mclk"); 131662306a36Sopenharmony_ci if (IS_ERR(mclk)) 131762306a36Sopenharmony_ci return PTR_ERR(mclk); 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci clocks->reg = of_iomap(np, 0); 132062306a36Sopenharmony_ci if (WARN_ON(!clocks->reg)) 132162306a36Sopenharmony_ci return -ENOMEM; 132262306a36Sopenharmony_ci 132362306a36Sopenharmony_ci r9a06g032_init_h2mode(clocks); 132462306a36Sopenharmony_ci 132562306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(r9a06g032_clocks); ++i) { 132662306a36Sopenharmony_ci const struct r9a06g032_clkdesc *d = &r9a06g032_clocks[i]; 132762306a36Sopenharmony_ci const char *parent_name = d->source ? 132862306a36Sopenharmony_ci __clk_get_name(clocks->data.clks[d->source - 1]) : 132962306a36Sopenharmony_ci __clk_get_name(mclk); 133062306a36Sopenharmony_ci struct clk *clk = NULL; 133162306a36Sopenharmony_ci 133262306a36Sopenharmony_ci switch (d->type) { 133362306a36Sopenharmony_ci case K_FFC: 133462306a36Sopenharmony_ci clk = clk_register_fixed_factor(NULL, d->name, 133562306a36Sopenharmony_ci parent_name, 0, 133662306a36Sopenharmony_ci d->mul, d->div); 133762306a36Sopenharmony_ci break; 133862306a36Sopenharmony_ci case K_GATE: 133962306a36Sopenharmony_ci clk = r9a06g032_register_gate(clocks, parent_name, d); 134062306a36Sopenharmony_ci break; 134162306a36Sopenharmony_ci case K_DIV: 134262306a36Sopenharmony_ci clk = r9a06g032_register_div(clocks, parent_name, d); 134362306a36Sopenharmony_ci break; 134462306a36Sopenharmony_ci case K_BITSEL: 134562306a36Sopenharmony_ci /* keep that selector register around */ 134662306a36Sopenharmony_ci uart_group_sel[d->dual.group] = d->dual.sel; 134762306a36Sopenharmony_ci clk = r9a06g032_register_bitsel(clocks, parent_name, d); 134862306a36Sopenharmony_ci break; 134962306a36Sopenharmony_ci case K_DUALGATE: 135062306a36Sopenharmony_ci clk = r9a06g032_register_dualgate(clocks, parent_name, 135162306a36Sopenharmony_ci d, 135262306a36Sopenharmony_ci uart_group_sel[d->dual.group]); 135362306a36Sopenharmony_ci break; 135462306a36Sopenharmony_ci } 135562306a36Sopenharmony_ci clocks->data.clks[d->index] = clk; 135662306a36Sopenharmony_ci } 135762306a36Sopenharmony_ci error = of_clk_add_provider(np, of_clk_src_onecell_get, &clocks->data); 135862306a36Sopenharmony_ci if (error) 135962306a36Sopenharmony_ci return error; 136062306a36Sopenharmony_ci 136162306a36Sopenharmony_ci error = devm_add_action_or_reset(dev, 136262306a36Sopenharmony_ci r9a06g032_clocks_del_clk_provider, np); 136362306a36Sopenharmony_ci if (error) 136462306a36Sopenharmony_ci return error; 136562306a36Sopenharmony_ci 136662306a36Sopenharmony_ci error = r9a06g032_add_clk_domain(dev); 136762306a36Sopenharmony_ci if (error) 136862306a36Sopenharmony_ci return error; 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci sysctrl_priv = clocks; 137162306a36Sopenharmony_ci 137262306a36Sopenharmony_ci error = of_platform_populate(np, NULL, NULL, dev); 137362306a36Sopenharmony_ci if (error) 137462306a36Sopenharmony_ci dev_err(dev, "Failed to populate children (%d)\n", error); 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ci return 0; 137762306a36Sopenharmony_ci} 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_cistatic const struct of_device_id r9a06g032_match[] = { 138062306a36Sopenharmony_ci { .compatible = "renesas,r9a06g032-sysctrl" }, 138162306a36Sopenharmony_ci { } 138262306a36Sopenharmony_ci}; 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_cistatic struct platform_driver r9a06g032_clock_driver = { 138562306a36Sopenharmony_ci .driver = { 138662306a36Sopenharmony_ci .name = "renesas,r9a06g032-sysctrl", 138762306a36Sopenharmony_ci .of_match_table = r9a06g032_match, 138862306a36Sopenharmony_ci }, 138962306a36Sopenharmony_ci}; 139062306a36Sopenharmony_ci 139162306a36Sopenharmony_cistatic int __init r9a06g032_clocks_init(void) 139262306a36Sopenharmony_ci{ 139362306a36Sopenharmony_ci return platform_driver_probe(&r9a06g032_clock_driver, 139462306a36Sopenharmony_ci r9a06g032_clocks_probe); 139562306a36Sopenharmony_ci} 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_cisubsys_initcall(r9a06g032_clocks_init); 1398