mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-01-09 11:00:52 +00:00
Merge branches 'clk-actions-reset', 'clk-imx7-init-critical', 'clk-mmp2-ids' and 'clk-at91-pmc-rework' into clk-next
- Reset Controller (RMU) support for Actions Semi Owl S900 and S700 SoCs - Rework at91 PMC clock driver for new DT bindings * clk-actions-reset: clk: actions: Add Actions Semi S900 SoC Reset Management Unit support clk: actions: Add Actions Semi S700 SoC Reset Management Unit support clk: actions: Add Actions Semi Owl SoCs Reset Management Unit support dt-bindings: reset: Add binding constants for Actions Semi S900 RMU dt-bindings: reset: Add binding constants for Actions Semi S700 RMU dt-bindings: clock: Add reset controller bindings for Actions Semi Owl SoCs clk: actions: Cache regmap info in private clock descriptor * clk-imx7-init-critical: clk: imx7d: remove CLK_IS_CRITICAL flag for arm_a7_root_clk clk: imx: cpu clock should be always critical clk: imx: imx7d: remove clks_init_on array clk: imx: imx7d: remove unnecessary clocks from clks_init_on array * clk-mmp2-ids: clk: mmp2: fix the clock id for sdh2_clk and sdh3_clk * clk-at91-pmc-rework: clk: at91: move DT compatibility code to its own file clk: at91: add at91sam9rl PMC driver clk: at91: add at91sam9x5 PMCs driver clk: at91: add at91sam9260 PMC driver clk: at91: add sama5d2 PMC driver clk: at91: add sama5d4 pmc driver clk: at91: add new DT lookup function dt-bindings: clk: at91: Document new PMC binding clk: at91: add pmc_data struct and helpers clk: at91: allow clock registration from C code clk: at91: generated: set audio_pll_allowed in at91_clk_register_generated() clk: at91: audio-pll: separate registration from DT parsing clk: at91: h32mx: separate registration from DT parsing clk: at91: generated: SSCs don't have a gclk clk: at91: audio-pll: fix audio pmc type
This commit is contained in:
commit
1fe7c040b6
@ -13,6 +13,7 @@ Required Properties:
|
||||
region.
|
||||
- clocks: Reference to the parent clocks ("hosc", "losc")
|
||||
- #clock-cells: should be 1.
|
||||
- #reset-cells: should be 1.
|
||||
|
||||
Each clock is assigned an identifier, and client nodes can use this identifier
|
||||
to specify the clock which they consume.
|
||||
@ -36,6 +37,7 @@ Example: Clock Management Unit node:
|
||||
reg = <0x0 0xe0160000 0x0 0x1000>;
|
||||
clocks = <&hosc>, <&losc>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
Example: UART controller node that consumes clock generated by the clock
|
||||
|
@ -4,6 +4,8 @@ This binding uses the common clock binding[1].
|
||||
|
||||
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
|
||||
Slow Clock controller:
|
||||
|
||||
Required properties:
|
||||
- compatible : shall be one of the following:
|
||||
"atmel,at91sam9x5-sckc" or
|
||||
@ -16,84 +18,6 @@ Required properties:
|
||||
|
||||
"atmel,at91sam9x5-clk-slow-rc-osc":
|
||||
at91 internal slow RC oscillator
|
||||
|
||||
"atmel,<chip>-pmc":
|
||||
at91 PMC (Power Management Controller)
|
||||
All at91 specific clocks (clocks defined below) must be child
|
||||
node of the PMC node.
|
||||
<chip> can be: at91rm9200, at91sam9260, at91sam9261,
|
||||
at91sam9263, at91sam9g45, at91sam9n12, at91sam9rl, at91sam9x5,
|
||||
sama5d2, sama5d3 or sama5d4.
|
||||
|
||||
"atmel,at91sam9x5-clk-slow" (under sckc node)
|
||||
or
|
||||
"atmel,at91sam9260-clk-slow" (under pmc node):
|
||||
at91 slow clk
|
||||
|
||||
"atmel,at91rm9200-clk-main-osc"
|
||||
"atmel,at91sam9x5-clk-main-rc-osc"
|
||||
at91 main clk sources
|
||||
|
||||
"atmel,at91sam9x5-clk-main"
|
||||
"atmel,at91rm9200-clk-main":
|
||||
at91 main clock
|
||||
|
||||
"atmel,at91rm9200-clk-master" or
|
||||
"atmel,at91sam9x5-clk-master":
|
||||
at91 master clock
|
||||
|
||||
"atmel,at91sam9x5-clk-peripheral" or
|
||||
"atmel,at91rm9200-clk-peripheral":
|
||||
at91 peripheral clocks
|
||||
|
||||
"atmel,at91rm9200-clk-pll" or
|
||||
"atmel,at91sam9g45-clk-pll" or
|
||||
"atmel,at91sam9g20-clk-pllb" or
|
||||
"atmel,sama5d3-clk-pll":
|
||||
at91 pll clocks
|
||||
|
||||
"atmel,at91sam9x5-clk-plldiv":
|
||||
at91 plla divisor
|
||||
|
||||
"atmel,at91rm9200-clk-programmable" or
|
||||
"atmel,at91sam9g45-clk-programmable" or
|
||||
"atmel,at91sam9x5-clk-programmable":
|
||||
at91 programmable clocks
|
||||
|
||||
"atmel,at91sam9x5-clk-smd":
|
||||
at91 SMD (Soft Modem) clock
|
||||
|
||||
"atmel,at91rm9200-clk-system":
|
||||
at91 system clocks
|
||||
|
||||
"atmel,at91rm9200-clk-usb" or
|
||||
"atmel,at91sam9x5-clk-usb" or
|
||||
"atmel,at91sam9n12-clk-usb":
|
||||
at91 usb clock
|
||||
|
||||
"atmel,at91sam9x5-clk-utmi":
|
||||
at91 utmi clock
|
||||
|
||||
"atmel,sama5d4-clk-h32mx":
|
||||
at91 h32mx clock
|
||||
|
||||
"atmel,sama5d2-clk-generated":
|
||||
at91 generated clock
|
||||
|
||||
"atmel,sama5d2-clk-audio-pll-frac":
|
||||
at91 audio fractional pll
|
||||
|
||||
"atmel,sama5d2-clk-audio-pll-pad":
|
||||
at91 audio pll CLK_AUDIO output pin
|
||||
|
||||
"atmel,sama5d2-clk-audio-pll-pmc"
|
||||
at91 audio pll output on AUDIOPLLCLK that feeds the PMC
|
||||
and can be used by peripheral clock or generic clock
|
||||
|
||||
"atmel,sama5d2-clk-i2s-mux" (under pmc node):
|
||||
at91 I2S clock source selection
|
||||
|
||||
Required properties for SCKC node:
|
||||
- reg : defines the IO memory reserved for the SCKC.
|
||||
- #size-cells : shall be 0 (reg is used to encode clk id).
|
||||
- #address-cells : shall be 1 (reg is used to encode clk id).
|
||||
@ -109,428 +33,30 @@ For example:
|
||||
/* put at91 slow clocks here */
|
||||
};
|
||||
|
||||
Power Management Controller (PMC):
|
||||
|
||||
Required properties for internal slow RC oscillator:
|
||||
- #clock-cells : from common clock binding; shall be set to 0.
|
||||
- clock-frequency : define the internal RC oscillator frequency.
|
||||
|
||||
Optional properties:
|
||||
- clock-accuracy : define the internal RC oscillator accuracy.
|
||||
|
||||
For example:
|
||||
slow_rc_osc: slow_rc_osc {
|
||||
compatible = "atmel,at91sam9x5-clk-slow-rc-osc";
|
||||
clock-frequency = <32768>;
|
||||
clock-accuracy = <50000000>;
|
||||
};
|
||||
|
||||
Required properties for slow oscillator:
|
||||
- #clock-cells : from common clock binding; shall be set to 0.
|
||||
- clocks : shall encode the main osc source clk sources (see atmel datasheet).
|
||||
Required properties:
|
||||
- compatible : shall be "atmel,<chip>-pmc", "syscon":
|
||||
<chip> can be: at91rm9200, at91sam9260, at91sam9261,
|
||||
at91sam9263, at91sam9g45, at91sam9n12, at91sam9rl, at91sam9g15,
|
||||
at91sam9g25, at91sam9g35, at91sam9x25, at91sam9x35, at91sam9x5,
|
||||
sama5d2, sama5d3 or sama5d4.
|
||||
- #clock-cells : from common clock binding; shall be set to 2. The first entry
|
||||
is the type of the clock (core, system, peripheral or generated) and the
|
||||
second entry its index as provided by the datasheet
|
||||
- clocks : Must contain an entry for each entry in clock-names.
|
||||
- clock-names: Must include the following entries: "slow_clk", "main_xtal"
|
||||
|
||||
Optional properties:
|
||||
- atmel,osc-bypass : boolean property. Set this when a clock signal is directly
|
||||
provided on XIN.
|
||||
|
||||
For example:
|
||||
slow_osc: slow_osc {
|
||||
compatible = "atmel,at91rm9200-clk-slow-osc";
|
||||
#clock-cells = <0>;
|
||||
clocks = <&slow_xtal>;
|
||||
};
|
||||
|
||||
Required properties for slow clock:
|
||||
- #clock-cells : from common clock binding; shall be set to 0.
|
||||
- clocks : shall encode the slow clk sources (see atmel datasheet).
|
||||
|
||||
For example:
|
||||
clk32k: slck {
|
||||
compatible = "atmel,at91sam9x5-clk-slow";
|
||||
#clock-cells = <0>;
|
||||
clocks = <&slow_rc_osc &slow_osc>;
|
||||
};
|
||||
|
||||
Required properties for PMC node:
|
||||
- reg : defines the IO memory reserved for the PMC.
|
||||
- #size-cells : shall be 0 (reg is used to encode clk id).
|
||||
- #address-cells : shall be 1 (reg is used to encode clk id).
|
||||
- interrupts : shall be set to PMC interrupt line.
|
||||
- interrupt-controller : tell that the PMC is an interrupt controller.
|
||||
- #interrupt-cells : must be set to 1. The first cell encodes the interrupt id,
|
||||
and reflect the bit position in the PMC_ER/DR/SR registers.
|
||||
You can use the dt macros defined in dt-bindings/clock/at91.h.
|
||||
0 (AT91_PMC_MOSCS) -> main oscillator ready
|
||||
1 (AT91_PMC_LOCKA) -> PLL A ready
|
||||
2 (AT91_PMC_LOCKB) -> PLL B ready
|
||||
3 (AT91_PMC_MCKRDY) -> master clock ready
|
||||
6 (AT91_PMC_LOCKU) -> UTMI PLL clock ready
|
||||
8 .. 15 (AT91_PMC_PCKRDY(id)) -> programmable clock ready
|
||||
16 (AT91_PMC_MOSCSELS) -> main oscillator selected
|
||||
17 (AT91_PMC_MOSCRCS) -> RC main oscillator stabilized
|
||||
18 (AT91_PMC_CFDEV) -> clock failure detected
|
||||
|
||||
For example:
|
||||
pmc: pmc@fffffc00 {
|
||||
compatible = "atmel,sama5d3-pmc";
|
||||
interrupts = <1 4 7>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
#size-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
|
||||
/* put at91 clocks here */
|
||||
};
|
||||
|
||||
Required properties for main clock internal RC oscillator:
|
||||
- interrupts : shall be set to "<0>".
|
||||
- clock-frequency : define the internal RC oscillator frequency.
|
||||
|
||||
Optional properties:
|
||||
- clock-accuracy : define the internal RC oscillator accuracy.
|
||||
|
||||
For example:
|
||||
main_rc_osc: main_rc_osc {
|
||||
compatible = "atmel,at91sam9x5-clk-main-rc-osc";
|
||||
interrupt-parent = <&pmc>;
|
||||
interrupts = <0>;
|
||||
clock-frequency = <12000000>;
|
||||
clock-accuracy = <50000000>;
|
||||
};
|
||||
|
||||
Required properties for main clock oscillator:
|
||||
- interrupts : shall be set to "<0>".
|
||||
- #clock-cells : from common clock binding; shall be set to 0.
|
||||
- clocks : shall encode the main osc source clk sources (see atmel datasheet).
|
||||
|
||||
Optional properties:
|
||||
- atmel,osc-bypass : boolean property. Specified if a clock signal is provided
|
||||
on XIN.
|
||||
|
||||
clock signal is directly provided on XIN pin.
|
||||
|
||||
For example:
|
||||
main_osc: main_osc {
|
||||
compatible = "atmel,at91rm9200-clk-main-osc";
|
||||
interrupt-parent = <&pmc>;
|
||||
interrupts = <0>;
|
||||
#clock-cells = <0>;
|
||||
clocks = <&main_xtal>;
|
||||
};
|
||||
|
||||
Required properties for main clock:
|
||||
- interrupts : shall be set to "<0>".
|
||||
- #clock-cells : from common clock binding; shall be set to 0.
|
||||
- clocks : shall encode the main clk sources (see atmel datasheet).
|
||||
|
||||
For example:
|
||||
main: mainck {
|
||||
compatible = "atmel,at91sam9x5-clk-main";
|
||||
interrupt-parent = <&pmc>;
|
||||
interrupts = <0>;
|
||||
#clock-cells = <0>;
|
||||
clocks = <&main_rc_osc &main_osc>;
|
||||
};
|
||||
|
||||
Required properties for master clock:
|
||||
- interrupts : shall be set to "<3>".
|
||||
- #clock-cells : from common clock binding; shall be set to 0.
|
||||
- clocks : shall be the master clock sources (see atmel datasheet) phandles.
|
||||
e.g. "<&ck32k>, <&main>, <&plla>, <&pllb>".
|
||||
- atmel,clk-output-range : minimum and maximum clock frequency (two u32
|
||||
fields).
|
||||
e.g. output = <0 133000000>; <=> 0 to 133MHz.
|
||||
- atmel,clk-divisors : master clock divisors table (four u32 fields).
|
||||
0 <=> reserved value.
|
||||
e.g. divisors = <1 2 4 6>;
|
||||
- atmel,master-clk-have-div3-pres : some SoC use the reserved value 7 in the
|
||||
PRES field as CLOCK_DIV3 (e.g sam9x5).
|
||||
|
||||
For example:
|
||||
mck: mck {
|
||||
compatible = "atmel,at91rm9200-clk-master";
|
||||
interrupt-parent = <&pmc>;
|
||||
interrupts = <3>;
|
||||
#clock-cells = <0>;
|
||||
atmel,clk-output-range = <0 133000000>;
|
||||
atmel,clk-divisors = <1 2 4 0>;
|
||||
};
|
||||
|
||||
Required properties for peripheral clocks:
|
||||
- #size-cells : shall be 0 (reg is used to encode clk id).
|
||||
- #address-cells : shall be 1 (reg is used to encode clk id).
|
||||
- clocks : shall be the master clock phandle.
|
||||
e.g. clocks = <&mck>;
|
||||
- name: device tree node describing a specific peripheral clock.
|
||||
* #clock-cells : from common clock binding; shall be set to 0.
|
||||
* reg: peripheral id. See Atmel's datasheets to get a full
|
||||
list of peripheral ids.
|
||||
* atmel,clk-output-range : minimum and maximum clock frequency
|
||||
(two u32 fields). Only valid on at91sam9x5-clk-peripheral
|
||||
compatible IPs.
|
||||
|
||||
For example:
|
||||
periph: periphck {
|
||||
compatible = "atmel,at91sam9x5-clk-peripheral";
|
||||
#size-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
clocks = <&mck>;
|
||||
|
||||
ssc0_clk {
|
||||
#clock-cells = <0>;
|
||||
reg = <2>;
|
||||
atmel,clk-output-range = <0 133000000>;
|
||||
};
|
||||
|
||||
usart0_clk {
|
||||
#clock-cells = <0>;
|
||||
reg = <3>;
|
||||
atmel,clk-output-range = <0 66000000>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Required properties for pll clocks:
|
||||
- interrupts : shall be set to "<1>".
|
||||
- #clock-cells : from common clock binding; shall be set to 0.
|
||||
- clocks : shall be the main clock phandle.
|
||||
- reg : pll id.
|
||||
0 -> PLL A
|
||||
1 -> PLL B
|
||||
- atmel,clk-input-range : minimum and maximum source clock frequency (two u32
|
||||
fields).
|
||||
e.g. input = <1 32000000>; <=> 1 to 32MHz.
|
||||
- #atmel,pll-clk-output-range-cells : number of cells reserved for pll output
|
||||
range description. Sould be set to 2, 3
|
||||
or 4.
|
||||
* 1st and 2nd cells represent the frequency range (min-max).
|
||||
* 3rd cell is optional and represents the OUT field value for the given
|
||||
range.
|
||||
* 4th cell is optional and represents the ICPLL field (PLLICPR
|
||||
register)
|
||||
- atmel,pll-clk-output-ranges : pll output frequency ranges + optional parameter
|
||||
depending on #atmel,pll-output-range-cells
|
||||
property value.
|
||||
|
||||
For example:
|
||||
plla: pllack {
|
||||
compatible = "atmel,at91sam9g45-clk-pll";
|
||||
interrupt-parent = <&pmc>;
|
||||
interrupts = <1>;
|
||||
#clock-cells = <0>;
|
||||
clocks = <&main>;
|
||||
reg = <0>;
|
||||
atmel,clk-input-range = <2000000 32000000>;
|
||||
#atmel,pll-clk-output-range-cells = <4>;
|
||||
atmel,pll-clk-output-ranges = <74500000 800000000 0 0
|
||||
69500000 750000000 1 0
|
||||
64500000 700000000 2 0
|
||||
59500000 650000000 3 0
|
||||
54500000 600000000 0 1
|
||||
49500000 550000000 1 1
|
||||
44500000 500000000 2 1
|
||||
40000000 450000000 3 1>;
|
||||
};
|
||||
|
||||
Required properties for plldiv clocks (plldiv = pll / 2):
|
||||
- #clock-cells : from common clock binding; shall be set to 0.
|
||||
- clocks : shall be the plla clock phandle.
|
||||
|
||||
The pll divisor is equal to 2 and cannot be changed.
|
||||
|
||||
For example:
|
||||
plladiv: plladivck {
|
||||
compatible = "atmel,at91sam9x5-clk-plldiv";
|
||||
#clock-cells = <0>;
|
||||
clocks = <&plla>;
|
||||
};
|
||||
|
||||
Required properties for programmable clocks:
|
||||
- #size-cells : shall be 0 (reg is used to encode clk id).
|
||||
- #address-cells : shall be 1 (reg is used to encode clk id).
|
||||
- clocks : shall be the programmable clock source phandles.
|
||||
e.g. clocks = <&clk32k>, <&main>, <&plla>, <&pllb>;
|
||||
- name: device tree node describing a specific prog clock.
|
||||
* #clock-cells : from common clock binding; shall be set to 0.
|
||||
* reg : programmable clock id (register offset from PCKx
|
||||
register).
|
||||
* interrupts : shall be set to "<(8 + id)>".
|
||||
|
||||
For example:
|
||||
prog: progck {
|
||||
compatible = "atmel,at91sam9g45-clk-programmable";
|
||||
#size-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
interrupt-parent = <&pmc>;
|
||||
clocks = <&clk32k>, <&main>, <&plladiv>, <&utmi>, <&mck>;
|
||||
|
||||
prog0 {
|
||||
#clock-cells = <0>;
|
||||
reg = <0>;
|
||||
interrupts = <8>;
|
||||
};
|
||||
|
||||
prog1 {
|
||||
#clock-cells = <0>;
|
||||
reg = <1>;
|
||||
interrupts = <9>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Required properties for smd clock:
|
||||
- #clock-cells : from common clock binding; shall be set to 0.
|
||||
- clocks : shall be the smd clock source phandles.
|
||||
e.g. clocks = <&plladiv>, <&utmi>;
|
||||
|
||||
For example:
|
||||
smd: smdck {
|
||||
compatible = "atmel,at91sam9x5-clk-smd";
|
||||
#clock-cells = <0>;
|
||||
clocks = <&plladiv>, <&utmi>;
|
||||
};
|
||||
|
||||
Required properties for system clocks:
|
||||
- #size-cells : shall be 0 (reg is used to encode clk id).
|
||||
- #address-cells : shall be 1 (reg is used to encode clk id).
|
||||
- name: device tree node describing a specific system clock.
|
||||
* #clock-cells : from common clock binding; shall be set to 0.
|
||||
* reg: system clock id (bit position in SCER/SCDR/SCSR registers).
|
||||
See Atmel's datasheet to get a full list of system clock ids.
|
||||
|
||||
For example:
|
||||
system: systemck {
|
||||
compatible = "atmel,at91rm9200-clk-system";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ddrck {
|
||||
#clock-cells = <0>;
|
||||
reg = <2>;
|
||||
clocks = <&mck>;
|
||||
};
|
||||
|
||||
uhpck {
|
||||
#clock-cells = <0>;
|
||||
reg = <6>;
|
||||
clocks = <&usb>;
|
||||
};
|
||||
|
||||
udpck {
|
||||
#clock-cells = <0>;
|
||||
reg = <7>;
|
||||
clocks = <&usb>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Required properties for usb clock:
|
||||
- #clock-cells : from common clock binding; shall be set to 0.
|
||||
- clocks : shall be the smd clock source phandles.
|
||||
e.g. clocks = <&pllb>;
|
||||
- atmel,clk-divisors (only available for "atmel,at91rm9200-clk-usb"):
|
||||
usb clock divisor table.
|
||||
e.g. divisors = <1 2 4 0>;
|
||||
|
||||
For example:
|
||||
usb: usbck {
|
||||
compatible = "atmel,at91sam9x5-clk-usb";
|
||||
#clock-cells = <0>;
|
||||
clocks = <&plladiv>, <&utmi>;
|
||||
};
|
||||
|
||||
usb: usbck {
|
||||
compatible = "atmel,at91rm9200-clk-usb";
|
||||
#clock-cells = <0>;
|
||||
clocks = <&pllb>;
|
||||
atmel,clk-divisors = <1 2 4 0>;
|
||||
};
|
||||
|
||||
|
||||
Required properties for utmi clock:
|
||||
- interrupts : shall be set to "<AT91_PMC_LOCKU IRQ_TYPE_LEVEL_HIGH>".
|
||||
- #clock-cells : from common clock binding; shall be set to 0.
|
||||
- clocks : shall be the main clock source phandle.
|
||||
|
||||
For example:
|
||||
utmi: utmick {
|
||||
compatible = "atmel,at91sam9x5-clk-utmi";
|
||||
interrupt-parent = <&pmc>;
|
||||
interrupts = <AT91_PMC_LOCKU IRQ_TYPE_LEVEL_HIGH>;
|
||||
#clock-cells = <0>;
|
||||
clocks = <&main>;
|
||||
};
|
||||
|
||||
Required properties for 32 bits bus Matrix clock (h32mx clock):
|
||||
- #clock-cells : from common clock binding; shall be set to 0.
|
||||
- clocks : shall be the master clock source phandle.
|
||||
|
||||
For example:
|
||||
h32ck: h32mxck {
|
||||
#clock-cells = <0>;
|
||||
compatible = "atmel,sama5d4-clk-h32mx";
|
||||
clocks = <&mck>;
|
||||
};
|
||||
|
||||
Required properties for generated clocks:
|
||||
- #size-cells : shall be 0 (reg is used to encode clk id).
|
||||
- #address-cells : shall be 1 (reg is used to encode clk id).
|
||||
- clocks : shall be the generated clock source phandles.
|
||||
e.g. clocks = <&clk32k>, <&main>, <&plladiv>, <&utmi>, <&mck>, <&audio_pll_pmc>;
|
||||
- name: device tree node describing a specific generated clock.
|
||||
* #clock-cells : from common clock binding; shall be set to 0.
|
||||
* reg: peripheral id. See Atmel's datasheets to get a full
|
||||
list of peripheral ids.
|
||||
* atmel,clk-output-range : minimum and maximum clock frequency
|
||||
(two u32 fields).
|
||||
|
||||
For example:
|
||||
gck {
|
||||
compatible = "atmel,sama5d2-clk-generated";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clocks = <&clk32k>, <&main>, <&plladiv>, <&utmi>, <&mck>, <&audio_pll_pmc>;
|
||||
|
||||
tcb0_gclk: tcb0_gclk {
|
||||
#clock-cells = <0>;
|
||||
reg = <35>;
|
||||
atmel,clk-output-range = <0 83000000>;
|
||||
};
|
||||
|
||||
pwm_gclk: pwm_gclk {
|
||||
#clock-cells = <0>;
|
||||
reg = <38>;
|
||||
atmel,clk-output-range = <0 83000000>;
|
||||
};
|
||||
};
|
||||
|
||||
Required properties for I2S mux clocks:
|
||||
- #size-cells : shall be 0 (reg is used to encode I2S bus id).
|
||||
- #address-cells : shall be 1 (reg is used to encode I2S bus id).
|
||||
- name: device tree node describing a specific mux clock.
|
||||
* #clock-cells : from common clock binding; shall be set to 0.
|
||||
* clocks : shall be the mux clock parent phandles; shall be 2 phandles:
|
||||
peripheral and generated clock; the first phandle shall belong to the
|
||||
peripheral clock and the second one shall belong to the generated
|
||||
clock; "clock-indices" property can be user to specify
|
||||
the correct order.
|
||||
* reg: I2S bus id of the corresponding mux clock.
|
||||
e.g. reg = <0>; for i2s0, reg = <1>; for i2s1
|
||||
|
||||
For example:
|
||||
i2s_clkmux {
|
||||
compatible = "atmel,sama5d2-clk-i2s-mux";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
i2s0muxck: i2s0_muxclk {
|
||||
clocks = <&i2s0_clk>, <&i2s0_gclk>;
|
||||
#clock-cells = <0>;
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
i2s1muxck: i2s1_muxclk {
|
||||
clocks = <&i2s1_clk>, <&i2s1_gclk>;
|
||||
#clock-cells = <0>;
|
||||
reg = <1>;
|
||||
};
|
||||
pmc: pmc@f0018000 {
|
||||
compatible = "atmel,sama5d4-pmc", "syscon";
|
||||
reg = <0xf0018000 0x120>;
|
||||
interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
|
||||
#clock-cells = <2>;
|
||||
clocks = <&clk32k>, <&main_xtal>;
|
||||
clock-names = "slow_clk", "main_xtal";
|
||||
};
|
||||
|
@ -2,6 +2,7 @@ config CLK_ACTIONS
|
||||
bool "Clock driver for Actions Semi SoCs"
|
||||
depends on ARCH_ACTIONS || COMPILE_TEST
|
||||
select REGMAP_MMIO
|
||||
select RESET_CONTROLLER
|
||||
default ARCH_ACTIONS
|
||||
|
||||
if CLK_ACTIONS
|
||||
|
@ -7,6 +7,7 @@ clk-owl-y += owl-divider.o
|
||||
clk-owl-y += owl-factor.o
|
||||
clk-owl-y += owl-composite.o
|
||||
clk-owl-y += owl-pll.o
|
||||
clk-owl-y += owl-reset.o
|
||||
|
||||
# SoC support
|
||||
obj-$(CONFIG_CLK_OWL_S700) += owl-s700.o
|
||||
|
@ -39,7 +39,7 @@ static void owl_clk_set_regmap(const struct owl_clk_desc *desc,
|
||||
}
|
||||
|
||||
int owl_clk_regmap_init(struct platform_device *pdev,
|
||||
const struct owl_clk_desc *desc)
|
||||
struct owl_clk_desc *desc)
|
||||
{
|
||||
void __iomem *base;
|
||||
struct regmap *regmap;
|
||||
@ -57,6 +57,7 @@ int owl_clk_regmap_init(struct platform_device *pdev,
|
||||
}
|
||||
|
||||
owl_clk_set_regmap(desc, regmap);
|
||||
desc->regmap = regmap;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -26,6 +26,9 @@ struct owl_clk_desc {
|
||||
struct owl_clk_common **clks;
|
||||
unsigned long num_clks;
|
||||
struct clk_hw_onecell_data *hw_clks;
|
||||
const struct owl_reset_map *resets;
|
||||
unsigned long num_resets;
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
static inline struct owl_clk_common *
|
||||
@ -35,7 +38,7 @@ static inline struct owl_clk_common *
|
||||
}
|
||||
|
||||
int owl_clk_regmap_init(struct platform_device *pdev,
|
||||
const struct owl_clk_desc *desc);
|
||||
struct owl_clk_desc *desc);
|
||||
int owl_clk_probe(struct device *dev, struct clk_hw_onecell_data *hw_clks);
|
||||
|
||||
#endif /* _OWL_COMMON_H_ */
|
||||
|
66
drivers/clk/actions/owl-reset.c
Normal file
66
drivers/clk/actions/owl-reset.c
Normal file
@ -0,0 +1,66 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
//
|
||||
// Actions Semi Owl SoCs Reset Management Unit driver
|
||||
//
|
||||
// Copyright (c) 2018 Linaro Ltd.
|
||||
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset-controller.h>
|
||||
|
||||
#include "owl-reset.h"
|
||||
|
||||
static int owl_reset_assert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct owl_reset *reset = to_owl_reset(rcdev);
|
||||
const struct owl_reset_map *map = &reset->reset_map[id];
|
||||
|
||||
return regmap_update_bits(reset->regmap, map->reg, map->bit, 0);
|
||||
}
|
||||
|
||||
static int owl_reset_deassert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct owl_reset *reset = to_owl_reset(rcdev);
|
||||
const struct owl_reset_map *map = &reset->reset_map[id];
|
||||
|
||||
return regmap_update_bits(reset->regmap, map->reg, map->bit, map->bit);
|
||||
}
|
||||
|
||||
static int owl_reset_reset(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
owl_reset_assert(rcdev, id);
|
||||
udelay(1);
|
||||
owl_reset_deassert(rcdev, id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int owl_reset_status(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct owl_reset *reset = to_owl_reset(rcdev);
|
||||
const struct owl_reset_map *map = &reset->reset_map[id];
|
||||
u32 reg;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(reset->regmap, map->reg, ®);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* The reset control API expects 0 if reset is not asserted,
|
||||
* which is the opposite of what our hardware uses.
|
||||
*/
|
||||
return !(map->bit & reg);
|
||||
}
|
||||
|
||||
const struct reset_control_ops owl_reset_ops = {
|
||||
.assert = owl_reset_assert,
|
||||
.deassert = owl_reset_deassert,
|
||||
.reset = owl_reset_reset,
|
||||
.status = owl_reset_status,
|
||||
};
|
31
drivers/clk/actions/owl-reset.h
Normal file
31
drivers/clk/actions/owl-reset.h
Normal file
@ -0,0 +1,31 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
//
|
||||
// Actions Semi Owl SoCs Reset Management Unit driver
|
||||
//
|
||||
// Copyright (c) 2018 Linaro Ltd.
|
||||
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||
|
||||
#ifndef _OWL_RESET_H_
|
||||
#define _OWL_RESET_H_
|
||||
|
||||
#include <linux/reset-controller.h>
|
||||
|
||||
struct owl_reset_map {
|
||||
u32 reg;
|
||||
u32 bit;
|
||||
};
|
||||
|
||||
struct owl_reset {
|
||||
struct reset_controller_dev rcdev;
|
||||
const struct owl_reset_map *reset_map;
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
static inline struct owl_reset *to_owl_reset(struct reset_controller_dev *rcdev)
|
||||
{
|
||||
return container_of(rcdev, struct owl_reset, rcdev);
|
||||
}
|
||||
|
||||
extern const struct reset_control_ops owl_reset_ops;
|
||||
|
||||
#endif /* _OWL_RESET_H_ */
|
@ -20,8 +20,10 @@
|
||||
#include "owl-gate.h"
|
||||
#include "owl-mux.h"
|
||||
#include "owl-pll.h"
|
||||
#include "owl-reset.h"
|
||||
|
||||
#include <dt-bindings/clock/actions,s700-cmu.h>
|
||||
#include <dt-bindings/reset/actions,s700-reset.h>
|
||||
|
||||
#define CMU_COREPLL (0x0000)
|
||||
#define CMU_DEVPLL (0x0004)
|
||||
@ -569,20 +571,69 @@ static struct clk_hw_onecell_data s700_hw_clks = {
|
||||
.num = CLK_NR_CLKS,
|
||||
};
|
||||
|
||||
static const struct owl_clk_desc s700_clk_desc = {
|
||||
static const struct owl_reset_map s700_resets[] = {
|
||||
[RESET_DE] = { CMU_DEVRST0, BIT(0) },
|
||||
[RESET_LCD0] = { CMU_DEVRST0, BIT(1) },
|
||||
[RESET_DSI] = { CMU_DEVRST0, BIT(2) },
|
||||
[RESET_CSI] = { CMU_DEVRST0, BIT(13) },
|
||||
[RESET_SI] = { CMU_DEVRST0, BIT(14) },
|
||||
[RESET_I2C0] = { CMU_DEVRST1, BIT(0) },
|
||||
[RESET_I2C1] = { CMU_DEVRST1, BIT(1) },
|
||||
[RESET_I2C2] = { CMU_DEVRST1, BIT(2) },
|
||||
[RESET_I2C3] = { CMU_DEVRST1, BIT(3) },
|
||||
[RESET_SPI0] = { CMU_DEVRST1, BIT(4) },
|
||||
[RESET_SPI1] = { CMU_DEVRST1, BIT(5) },
|
||||
[RESET_SPI2] = { CMU_DEVRST1, BIT(6) },
|
||||
[RESET_SPI3] = { CMU_DEVRST1, BIT(7) },
|
||||
[RESET_UART0] = { CMU_DEVRST1, BIT(8) },
|
||||
[RESET_UART1] = { CMU_DEVRST1, BIT(9) },
|
||||
[RESET_UART2] = { CMU_DEVRST1, BIT(10) },
|
||||
[RESET_UART3] = { CMU_DEVRST1, BIT(11) },
|
||||
[RESET_UART4] = { CMU_DEVRST1, BIT(12) },
|
||||
[RESET_UART5] = { CMU_DEVRST1, BIT(13) },
|
||||
[RESET_UART6] = { CMU_DEVRST1, BIT(14) },
|
||||
[RESET_KEY] = { CMU_DEVRST1, BIT(24) },
|
||||
[RESET_GPIO] = { CMU_DEVRST1, BIT(25) },
|
||||
[RESET_AUDIO] = { CMU_DEVRST1, BIT(29) },
|
||||
};
|
||||
|
||||
static struct owl_clk_desc s700_clk_desc = {
|
||||
.clks = s700_clks,
|
||||
.num_clks = ARRAY_SIZE(s700_clks),
|
||||
|
||||
.hw_clks = &s700_hw_clks,
|
||||
|
||||
.resets = s700_resets,
|
||||
.num_resets = ARRAY_SIZE(s700_resets),
|
||||
};
|
||||
|
||||
static int s700_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct owl_clk_desc *desc;
|
||||
struct owl_clk_desc *desc;
|
||||
struct owl_reset *reset;
|
||||
int ret;
|
||||
|
||||
desc = &s700_clk_desc;
|
||||
owl_clk_regmap_init(pdev, desc);
|
||||
|
||||
/*
|
||||
* FIXME: Reset controller registration should be moved to
|
||||
* common code, once all SoCs of Owl family supports it.
|
||||
*/
|
||||
reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
|
||||
if (!reset)
|
||||
return -ENOMEM;
|
||||
|
||||
reset->rcdev.of_node = pdev->dev.of_node;
|
||||
reset->rcdev.ops = &owl_reset_ops;
|
||||
reset->rcdev.nr_resets = desc->num_resets;
|
||||
reset->reset_map = desc->resets;
|
||||
reset->regmap = desc->regmap;
|
||||
|
||||
ret = devm_reset_controller_register(&pdev->dev, &reset->rcdev);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "Failed to register reset controller\n");
|
||||
|
||||
return owl_clk_probe(&pdev->dev, desc->hw_clks);
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,10 @@
|
||||
#include "owl-gate.h"
|
||||
#include "owl-mux.h"
|
||||
#include "owl-pll.h"
|
||||
#include "owl-reset.h"
|
||||
|
||||
#include <dt-bindings/clock/actions,s900-cmu.h>
|
||||
#include <dt-bindings/reset/actions,s900-reset.h>
|
||||
|
||||
#define CMU_COREPLL (0x0000)
|
||||
#define CMU_DEVPLL (0x0004)
|
||||
@ -684,20 +686,100 @@ static struct clk_hw_onecell_data s900_hw_clks = {
|
||||
.num = CLK_NR_CLKS,
|
||||
};
|
||||
|
||||
static const struct owl_clk_desc s900_clk_desc = {
|
||||
static const struct owl_reset_map s900_resets[] = {
|
||||
[RESET_DMAC] = { CMU_DEVRST0, BIT(0) },
|
||||
[RESET_SRAMI] = { CMU_DEVRST0, BIT(1) },
|
||||
[RESET_DDR_CTL_PHY] = { CMU_DEVRST0, BIT(2) },
|
||||
[RESET_NANDC0] = { CMU_DEVRST0, BIT(3) },
|
||||
[RESET_SD0] = { CMU_DEVRST0, BIT(4) },
|
||||
[RESET_SD1] = { CMU_DEVRST0, BIT(5) },
|
||||
[RESET_PCM1] = { CMU_DEVRST0, BIT(6) },
|
||||
[RESET_DE] = { CMU_DEVRST0, BIT(7) },
|
||||
[RESET_LVDS] = { CMU_DEVRST0, BIT(8) },
|
||||
[RESET_SD2] = { CMU_DEVRST0, BIT(9) },
|
||||
[RESET_DSI] = { CMU_DEVRST0, BIT(10) },
|
||||
[RESET_CSI0] = { CMU_DEVRST0, BIT(11) },
|
||||
[RESET_BISP_AXI] = { CMU_DEVRST0, BIT(12) },
|
||||
[RESET_CSI1] = { CMU_DEVRST0, BIT(13) },
|
||||
[RESET_GPIO] = { CMU_DEVRST0, BIT(15) },
|
||||
[RESET_EDP] = { CMU_DEVRST0, BIT(16) },
|
||||
[RESET_AUDIO] = { CMU_DEVRST0, BIT(17) },
|
||||
[RESET_PCM0] = { CMU_DEVRST0, BIT(18) },
|
||||
[RESET_HDE] = { CMU_DEVRST0, BIT(21) },
|
||||
[RESET_GPU3D_PA] = { CMU_DEVRST0, BIT(22) },
|
||||
[RESET_IMX] = { CMU_DEVRST0, BIT(23) },
|
||||
[RESET_SE] = { CMU_DEVRST0, BIT(24) },
|
||||
[RESET_NANDC1] = { CMU_DEVRST0, BIT(25) },
|
||||
[RESET_SD3] = { CMU_DEVRST0, BIT(26) },
|
||||
[RESET_GIC] = { CMU_DEVRST0, BIT(27) },
|
||||
[RESET_GPU3D_PB] = { CMU_DEVRST0, BIT(28) },
|
||||
[RESET_DDR_CTL_PHY_AXI] = { CMU_DEVRST0, BIT(29) },
|
||||
[RESET_CMU_DDR] = { CMU_DEVRST0, BIT(30) },
|
||||
[RESET_DMM] = { CMU_DEVRST0, BIT(31) },
|
||||
[RESET_USB2HUB] = { CMU_DEVRST1, BIT(0) },
|
||||
[RESET_USB2HSIC] = { CMU_DEVRST1, BIT(1) },
|
||||
[RESET_HDMI] = { CMU_DEVRST1, BIT(2) },
|
||||
[RESET_HDCP2TX] = { CMU_DEVRST1, BIT(3) },
|
||||
[RESET_UART6] = { CMU_DEVRST1, BIT(4) },
|
||||
[RESET_UART0] = { CMU_DEVRST1, BIT(5) },
|
||||
[RESET_UART1] = { CMU_DEVRST1, BIT(6) },
|
||||
[RESET_UART2] = { CMU_DEVRST1, BIT(7) },
|
||||
[RESET_SPI0] = { CMU_DEVRST1, BIT(8) },
|
||||
[RESET_SPI1] = { CMU_DEVRST1, BIT(9) },
|
||||
[RESET_SPI2] = { CMU_DEVRST1, BIT(10) },
|
||||
[RESET_SPI3] = { CMU_DEVRST1, BIT(11) },
|
||||
[RESET_I2C0] = { CMU_DEVRST1, BIT(12) },
|
||||
[RESET_I2C1] = { CMU_DEVRST1, BIT(13) },
|
||||
[RESET_USB3] = { CMU_DEVRST1, BIT(14) },
|
||||
[RESET_UART3] = { CMU_DEVRST1, BIT(15) },
|
||||
[RESET_UART4] = { CMU_DEVRST1, BIT(16) },
|
||||
[RESET_UART5] = { CMU_DEVRST1, BIT(17) },
|
||||
[RESET_I2C2] = { CMU_DEVRST1, BIT(18) },
|
||||
[RESET_I2C3] = { CMU_DEVRST1, BIT(19) },
|
||||
[RESET_ETHERNET] = { CMU_DEVRST1, BIT(20) },
|
||||
[RESET_CHIPID] = { CMU_DEVRST1, BIT(21) },
|
||||
[RESET_I2C4] = { CMU_DEVRST1, BIT(22) },
|
||||
[RESET_I2C5] = { CMU_DEVRST1, BIT(23) },
|
||||
[RESET_CPU_SCNT] = { CMU_DEVRST1, BIT(30) }
|
||||
};
|
||||
|
||||
static struct owl_clk_desc s900_clk_desc = {
|
||||
.clks = s900_clks,
|
||||
.num_clks = ARRAY_SIZE(s900_clks),
|
||||
|
||||
.hw_clks = &s900_hw_clks,
|
||||
|
||||
.resets = s900_resets,
|
||||
.num_resets = ARRAY_SIZE(s900_resets),
|
||||
};
|
||||
|
||||
static int s900_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct owl_clk_desc *desc;
|
||||
struct owl_clk_desc *desc;
|
||||
struct owl_reset *reset;
|
||||
int ret;
|
||||
|
||||
desc = &s900_clk_desc;
|
||||
owl_clk_regmap_init(pdev, desc);
|
||||
|
||||
/*
|
||||
* FIXME: Reset controller registration should be moved to
|
||||
* common code, once all SoCs of Owl family supports it.
|
||||
*/
|
||||
reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
|
||||
if (!reset)
|
||||
return -ENOMEM;
|
||||
|
||||
reset->rcdev.of_node = pdev->dev.of_node;
|
||||
reset->rcdev.ops = &owl_reset_ops;
|
||||
reset->rcdev.nr_resets = desc->num_resets;
|
||||
reset->reset_map = desc->resets;
|
||||
reset->regmap = desc->regmap;
|
||||
|
||||
ret = devm_reset_controller_register(&pdev->dev, &reset->rcdev);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "Failed to register reset controller\n");
|
||||
|
||||
return owl_clk_probe(&pdev->dev, desc->hw_clks);
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
# Makefile for at91 specific clk
|
||||
#
|
||||
|
||||
obj-y += pmc.o sckc.o
|
||||
obj-y += pmc.o sckc.o dt-compat.o
|
||||
obj-y += clk-slow.o clk-main.o clk-pll.o clk-plldiv.o clk-master.o
|
||||
obj-y += clk-system.o clk-peripheral.o clk-programmable.o
|
||||
|
||||
@ -14,3 +14,6 @@ obj-$(CONFIG_HAVE_AT91_SMD) += clk-smd.o
|
||||
obj-$(CONFIG_HAVE_AT91_H32MX) += clk-h32mx.o
|
||||
obj-$(CONFIG_HAVE_AT91_GENERATED_CLK) += clk-generated.o
|
||||
obj-$(CONFIG_HAVE_AT91_I2S_MUX_CLK) += clk-i2s-mux.o
|
||||
obj-$(CONFIG_SOC_AT91SAM9) += at91sam9260.o at91sam9rl.o at91sam9x5.o
|
||||
obj-$(CONFIG_SOC_SAMA5D4) += sama5d4.o
|
||||
obj-$(CONFIG_SOC_SAMA5D2) += sama5d2.o
|
||||
|
494
drivers/clk/at91/at91sam9260.c
Normal file
494
drivers/clk/at91/at91sam9260.c
Normal file
@ -0,0 +1,494 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dt-bindings/clock/at91.h>
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
struct sck {
|
||||
char *n;
|
||||
char *p;
|
||||
u8 id;
|
||||
};
|
||||
|
||||
struct pck {
|
||||
char *n;
|
||||
u8 id;
|
||||
};
|
||||
|
||||
struct at91sam926x_data {
|
||||
const struct clk_pll_layout *plla_layout;
|
||||
const struct clk_pll_characteristics *plla_characteristics;
|
||||
const struct clk_pll_layout *pllb_layout;
|
||||
const struct clk_pll_characteristics *pllb_characteristics;
|
||||
const struct clk_master_characteristics *mck_characteristics;
|
||||
const struct sck *sck;
|
||||
const struct pck *pck;
|
||||
u8 num_sck;
|
||||
u8 num_pck;
|
||||
u8 num_progck;
|
||||
bool has_slck;
|
||||
};
|
||||
|
||||
static const struct clk_master_characteristics sam9260_mck_characteristics = {
|
||||
.output = { .min = 0, .max = 105000000 },
|
||||
.divisors = { 1, 2, 4, 0 },
|
||||
};
|
||||
|
||||
static u8 sam9260_plla_out[] = { 0, 2 };
|
||||
|
||||
static u16 sam9260_plla_icpll[] = { 1, 1 };
|
||||
|
||||
static struct clk_range sam9260_plla_outputs[] = {
|
||||
{ .min = 80000000, .max = 160000000 },
|
||||
{ .min = 150000000, .max = 240000000 },
|
||||
};
|
||||
|
||||
static const struct clk_pll_characteristics sam9260_plla_characteristics = {
|
||||
.input = { .min = 1000000, .max = 32000000 },
|
||||
.num_output = ARRAY_SIZE(sam9260_plla_outputs),
|
||||
.output = sam9260_plla_outputs,
|
||||
.icpll = sam9260_plla_icpll,
|
||||
.out = sam9260_plla_out,
|
||||
};
|
||||
|
||||
static u8 sam9260_pllb_out[] = { 1 };
|
||||
|
||||
static u16 sam9260_pllb_icpll[] = { 1 };
|
||||
|
||||
static struct clk_range sam9260_pllb_outputs[] = {
|
||||
{ .min = 70000000, .max = 130000000 },
|
||||
};
|
||||
|
||||
static const struct clk_pll_characteristics sam9260_pllb_characteristics = {
|
||||
.input = { .min = 1000000, .max = 5000000 },
|
||||
.num_output = ARRAY_SIZE(sam9260_pllb_outputs),
|
||||
.output = sam9260_pllb_outputs,
|
||||
.icpll = sam9260_pllb_icpll,
|
||||
.out = sam9260_pllb_out,
|
||||
};
|
||||
|
||||
static const struct sck at91sam9260_systemck[] = {
|
||||
{ .n = "uhpck", .p = "usbck", .id = 6 },
|
||||
{ .n = "udpck", .p = "usbck", .id = 7 },
|
||||
{ .n = "pck0", .p = "prog0", .id = 8 },
|
||||
{ .n = "pck1", .p = "prog1", .id = 9 },
|
||||
};
|
||||
|
||||
static const struct pck at91sam9260_periphck[] = {
|
||||
{ .n = "pioA_clk", .id = 2 },
|
||||
{ .n = "pioB_clk", .id = 3 },
|
||||
{ .n = "pioC_clk", .id = 4 },
|
||||
{ .n = "adc_clk", .id = 5 },
|
||||
{ .n = "usart0_clk", .id = 6 },
|
||||
{ .n = "usart1_clk", .id = 7 },
|
||||
{ .n = "usart2_clk", .id = 8 },
|
||||
{ .n = "mci0_clk", .id = 9 },
|
||||
{ .n = "udc_clk", .id = 10 },
|
||||
{ .n = "twi0_clk", .id = 11 },
|
||||
{ .n = "spi0_clk", .id = 12 },
|
||||
{ .n = "spi1_clk", .id = 13 },
|
||||
{ .n = "ssc0_clk", .id = 14 },
|
||||
{ .n = "tc0_clk", .id = 17 },
|
||||
{ .n = "tc1_clk", .id = 18 },
|
||||
{ .n = "tc2_clk", .id = 19 },
|
||||
{ .n = "ohci_clk", .id = 20 },
|
||||
{ .n = "macb0_clk", .id = 21 },
|
||||
{ .n = "isi_clk", .id = 22 },
|
||||
{ .n = "usart3_clk", .id = 23 },
|
||||
{ .n = "uart0_clk", .id = 24 },
|
||||
{ .n = "uart1_clk", .id = 25 },
|
||||
{ .n = "tc3_clk", .id = 26 },
|
||||
{ .n = "tc4_clk", .id = 27 },
|
||||
{ .n = "tc5_clk", .id = 28 },
|
||||
};
|
||||
|
||||
static struct at91sam926x_data at91sam9260_data = {
|
||||
.plla_layout = &at91rm9200_pll_layout,
|
||||
.plla_characteristics = &sam9260_plla_characteristics,
|
||||
.pllb_layout = &at91rm9200_pll_layout,
|
||||
.pllb_characteristics = &sam9260_pllb_characteristics,
|
||||
.mck_characteristics = &sam9260_mck_characteristics,
|
||||
.sck = at91sam9260_systemck,
|
||||
.num_sck = ARRAY_SIZE(at91sam9260_systemck),
|
||||
.pck = at91sam9260_periphck,
|
||||
.num_pck = ARRAY_SIZE(at91sam9260_periphck),
|
||||
.num_progck = 2,
|
||||
.has_slck = true,
|
||||
};
|
||||
|
||||
static const struct clk_master_characteristics sam9g20_mck_characteristics = {
|
||||
.output = { .min = 0, .max = 133000000 },
|
||||
.divisors = { 1, 2, 4, 6 },
|
||||
};
|
||||
|
||||
static u8 sam9g20_plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 };
|
||||
|
||||
static u16 sam9g20_plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 };
|
||||
|
||||
static struct clk_range sam9g20_plla_outputs[] = {
|
||||
{ .min = 745000000, .max = 800000000 },
|
||||
{ .min = 695000000, .max = 750000000 },
|
||||
{ .min = 645000000, .max = 700000000 },
|
||||
{ .min = 595000000, .max = 650000000 },
|
||||
{ .min = 545000000, .max = 600000000 },
|
||||
{ .min = 495000000, .max = 550000000 },
|
||||
{ .min = 445000000, .max = 500000000 },
|
||||
{ .min = 400000000, .max = 450000000 },
|
||||
};
|
||||
|
||||
static const struct clk_pll_characteristics sam9g20_plla_characteristics = {
|
||||
.input = { .min = 2000000, .max = 32000000 },
|
||||
.num_output = ARRAY_SIZE(sam9g20_plla_outputs),
|
||||
.output = sam9g20_plla_outputs,
|
||||
.icpll = sam9g20_plla_icpll,
|
||||
.out = sam9g20_plla_out,
|
||||
};
|
||||
|
||||
static u8 sam9g20_pllb_out[] = { 0 };
|
||||
|
||||
static u16 sam9g20_pllb_icpll[] = { 0 };
|
||||
|
||||
static struct clk_range sam9g20_pllb_outputs[] = {
|
||||
{ .min = 30000000, .max = 100000000 },
|
||||
};
|
||||
|
||||
static const struct clk_pll_characteristics sam9g20_pllb_characteristics = {
|
||||
.input = { .min = 2000000, .max = 32000000 },
|
||||
.num_output = ARRAY_SIZE(sam9g20_pllb_outputs),
|
||||
.output = sam9g20_pllb_outputs,
|
||||
.icpll = sam9g20_pllb_icpll,
|
||||
.out = sam9g20_pllb_out,
|
||||
};
|
||||
|
||||
static struct at91sam926x_data at91sam9g20_data = {
|
||||
.plla_layout = &at91sam9g45_pll_layout,
|
||||
.plla_characteristics = &sam9g20_plla_characteristics,
|
||||
.pllb_layout = &at91sam9g20_pllb_layout,
|
||||
.pllb_characteristics = &sam9g20_pllb_characteristics,
|
||||
.mck_characteristics = &sam9g20_mck_characteristics,
|
||||
.sck = at91sam9260_systemck,
|
||||
.num_sck = ARRAY_SIZE(at91sam9260_systemck),
|
||||
.pck = at91sam9260_periphck,
|
||||
.num_pck = ARRAY_SIZE(at91sam9260_periphck),
|
||||
.num_progck = 2,
|
||||
.has_slck = true,
|
||||
};
|
||||
|
||||
static const struct clk_master_characteristics sam9261_mck_characteristics = {
|
||||
.output = { .min = 0, .max = 94000000 },
|
||||
.divisors = { 1, 2, 4, 0 },
|
||||
};
|
||||
|
||||
static struct clk_range sam9261_plla_outputs[] = {
|
||||
{ .min = 80000000, .max = 200000000 },
|
||||
{ .min = 190000000, .max = 240000000 },
|
||||
};
|
||||
|
||||
static const struct clk_pll_characteristics sam9261_plla_characteristics = {
|
||||
.input = { .min = 1000000, .max = 32000000 },
|
||||
.num_output = ARRAY_SIZE(sam9261_plla_outputs),
|
||||
.output = sam9261_plla_outputs,
|
||||
.icpll = sam9260_plla_icpll,
|
||||
.out = sam9260_plla_out,
|
||||
};
|
||||
|
||||
static u8 sam9261_pllb_out[] = { 1 };
|
||||
|
||||
static u16 sam9261_pllb_icpll[] = { 1 };
|
||||
|
||||
static struct clk_range sam9261_pllb_outputs[] = {
|
||||
{ .min = 70000000, .max = 130000000 },
|
||||
};
|
||||
|
||||
static const struct clk_pll_characteristics sam9261_pllb_characteristics = {
|
||||
.input = { .min = 1000000, .max = 5000000 },
|
||||
.num_output = ARRAY_SIZE(sam9261_pllb_outputs),
|
||||
.output = sam9261_pllb_outputs,
|
||||
.icpll = sam9261_pllb_icpll,
|
||||
.out = sam9261_pllb_out,
|
||||
};
|
||||
|
||||
static const struct sck at91sam9261_systemck[] = {
|
||||
{ .n = "uhpck", .p = "usbck", .id = 6 },
|
||||
{ .n = "udpck", .p = "usbck", .id = 7 },
|
||||
{ .n = "pck0", .p = "prog0", .id = 8 },
|
||||
{ .n = "pck1", .p = "prog1", .id = 9 },
|
||||
{ .n = "pck2", .p = "prog2", .id = 10 },
|
||||
{ .n = "pck3", .p = "prog3", .id = 11 },
|
||||
{ .n = "hclk0", .p = "masterck", .id = 16 },
|
||||
{ .n = "hclk1", .p = "masterck", .id = 17 },
|
||||
};
|
||||
|
||||
static const struct pck at91sam9261_periphck[] = {
|
||||
{ .n = "pioA_clk", .id = 2, },
|
||||
{ .n = "pioB_clk", .id = 3, },
|
||||
{ .n = "pioC_clk", .id = 4, },
|
||||
{ .n = "usart0_clk", .id = 6, },
|
||||
{ .n = "usart1_clk", .id = 7, },
|
||||
{ .n = "usart2_clk", .id = 8, },
|
||||
{ .n = "mci0_clk", .id = 9, },
|
||||
{ .n = "udc_clk", .id = 10, },
|
||||
{ .n = "twi0_clk", .id = 11, },
|
||||
{ .n = "spi0_clk", .id = 12, },
|
||||
{ .n = "spi1_clk", .id = 13, },
|
||||
{ .n = "ssc0_clk", .id = 14, },
|
||||
{ .n = "ssc1_clk", .id = 15, },
|
||||
{ .n = "ssc2_clk", .id = 16, },
|
||||
{ .n = "tc0_clk", .id = 17, },
|
||||
{ .n = "tc1_clk", .id = 18, },
|
||||
{ .n = "tc2_clk", .id = 19, },
|
||||
{ .n = "ohci_clk", .id = 20, },
|
||||
{ .n = "lcd_clk", .id = 21, },
|
||||
};
|
||||
|
||||
static struct at91sam926x_data at91sam9261_data = {
|
||||
.plla_layout = &at91rm9200_pll_layout,
|
||||
.plla_characteristics = &sam9261_plla_characteristics,
|
||||
.pllb_layout = &at91rm9200_pll_layout,
|
||||
.pllb_characteristics = &sam9261_pllb_characteristics,
|
||||
.mck_characteristics = &sam9261_mck_characteristics,
|
||||
.sck = at91sam9261_systemck,
|
||||
.num_sck = ARRAY_SIZE(at91sam9261_systemck),
|
||||
.pck = at91sam9261_periphck,
|
||||
.num_pck = ARRAY_SIZE(at91sam9261_periphck),
|
||||
.num_progck = 4,
|
||||
};
|
||||
|
||||
static const struct clk_master_characteristics sam9263_mck_characteristics = {
|
||||
.output = { .min = 0, .max = 120000000 },
|
||||
.divisors = { 1, 2, 4, 0 },
|
||||
};
|
||||
|
||||
static struct clk_range sam9263_pll_outputs[] = {
|
||||
{ .min = 80000000, .max = 200000000 },
|
||||
{ .min = 190000000, .max = 240000000 },
|
||||
};
|
||||
|
||||
static const struct clk_pll_characteristics sam9263_pll_characteristics = {
|
||||
.input = { .min = 1000000, .max = 32000000 },
|
||||
.num_output = ARRAY_SIZE(sam9263_pll_outputs),
|
||||
.output = sam9263_pll_outputs,
|
||||
.icpll = sam9260_plla_icpll,
|
||||
.out = sam9260_plla_out,
|
||||
};
|
||||
|
||||
static const struct sck at91sam9263_systemck[] = {
|
||||
{ .n = "uhpck", .p = "usbck", .id = 6 },
|
||||
{ .n = "udpck", .p = "usbck", .id = 7 },
|
||||
{ .n = "pck0", .p = "prog0", .id = 8 },
|
||||
{ .n = "pck1", .p = "prog1", .id = 9 },
|
||||
{ .n = "pck2", .p = "prog2", .id = 10 },
|
||||
{ .n = "pck3", .p = "prog3", .id = 11 },
|
||||
};
|
||||
|
||||
static const struct pck at91sam9263_periphck[] = {
|
||||
{ .n = "pioA_clk", .id = 2, },
|
||||
{ .n = "pioB_clk", .id = 3, },
|
||||
{ .n = "pioCDE_clk", .id = 4, },
|
||||
{ .n = "usart0_clk", .id = 7, },
|
||||
{ .n = "usart1_clk", .id = 8, },
|
||||
{ .n = "usart2_clk", .id = 9, },
|
||||
{ .n = "mci0_clk", .id = 10, },
|
||||
{ .n = "mci1_clk", .id = 11, },
|
||||
{ .n = "can_clk", .id = 12, },
|
||||
{ .n = "twi0_clk", .id = 13, },
|
||||
{ .n = "spi0_clk", .id = 14, },
|
||||
{ .n = "spi1_clk", .id = 15, },
|
||||
{ .n = "ssc0_clk", .id = 16, },
|
||||
{ .n = "ssc1_clk", .id = 17, },
|
||||
{ .n = "ac97_clk", .id = 18, },
|
||||
{ .n = "tcb_clk", .id = 19, },
|
||||
{ .n = "pwm_clk", .id = 20, },
|
||||
{ .n = "macb0_clk", .id = 21, },
|
||||
{ .n = "g2de_clk", .id = 23, },
|
||||
{ .n = "udc_clk", .id = 24, },
|
||||
{ .n = "isi_clk", .id = 25, },
|
||||
{ .n = "lcd_clk", .id = 26, },
|
||||
{ .n = "dma_clk", .id = 27, },
|
||||
{ .n = "ohci_clk", .id = 29, },
|
||||
};
|
||||
|
||||
static struct at91sam926x_data at91sam9263_data = {
|
||||
.plla_layout = &at91rm9200_pll_layout,
|
||||
.plla_characteristics = &sam9263_pll_characteristics,
|
||||
.pllb_layout = &at91rm9200_pll_layout,
|
||||
.pllb_characteristics = &sam9263_pll_characteristics,
|
||||
.mck_characteristics = &sam9263_mck_characteristics,
|
||||
.sck = at91sam9263_systemck,
|
||||
.num_sck = ARRAY_SIZE(at91sam9263_systemck),
|
||||
.pck = at91sam9263_periphck,
|
||||
.num_pck = ARRAY_SIZE(at91sam9263_periphck),
|
||||
.num_progck = 4,
|
||||
};
|
||||
|
||||
static void __init at91sam926x_pmc_setup(struct device_node *np,
|
||||
struct at91sam926x_data *data)
|
||||
{
|
||||
const char *slowxtal_name, *mainxtal_name;
|
||||
struct pmc_data *at91sam9260_pmc;
|
||||
u32 usb_div[] = { 1, 2, 4, 0 };
|
||||
const char *parent_names[6];
|
||||
const char *slck_name;
|
||||
struct regmap *regmap;
|
||||
struct clk_hw *hw;
|
||||
int i;
|
||||
bool bypass;
|
||||
|
||||
i = of_property_match_string(np, "clock-names", "slow_xtal");
|
||||
if (i < 0)
|
||||
return;
|
||||
|
||||
slowxtal_name = of_clk_get_parent_name(np, i);
|
||||
|
||||
i = of_property_match_string(np, "clock-names", "main_xtal");
|
||||
if (i < 0)
|
||||
return;
|
||||
mainxtal_name = of_clk_get_parent_name(np, i);
|
||||
|
||||
regmap = syscon_node_to_regmap(np);
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
at91sam9260_pmc = pmc_data_allocate(PMC_MAIN + 1,
|
||||
ndck(data->sck, data->num_sck),
|
||||
ndck(data->pck, data->num_pck), 0);
|
||||
if (!at91sam9260_pmc)
|
||||
return;
|
||||
|
||||
bypass = of_property_read_bool(np, "atmel,osc-bypass");
|
||||
|
||||
hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
|
||||
bypass);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_rm9200_main(regmap, "mainck", "main_osc");
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9260_pmc->chws[PMC_MAIN] = hw;
|
||||
|
||||
if (data->has_slck) {
|
||||
hw = clk_hw_register_fixed_rate_with_accuracy(NULL,
|
||||
"slow_rc_osc",
|
||||
NULL, 0, 32768,
|
||||
50000000);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
parent_names[0] = "slow_rc_osc";
|
||||
parent_names[1] = "slow_xtal";
|
||||
hw = at91_clk_register_sam9260_slow(regmap, "slck",
|
||||
parent_names, 2);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9260_pmc->chws[PMC_SLOW] = hw;
|
||||
slck_name = "slck";
|
||||
} else {
|
||||
slck_name = slowxtal_name;
|
||||
}
|
||||
|
||||
hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
|
||||
data->plla_layout,
|
||||
data->plla_characteristics);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_pll(regmap, "pllbck", "mainck", 1,
|
||||
data->pllb_layout,
|
||||
data->pllb_characteristics);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
parent_names[0] = slck_name;
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "pllack";
|
||||
parent_names[3] = "pllbck";
|
||||
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
|
||||
&at91rm9200_master_layout,
|
||||
data->mck_characteristics);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9260_pmc->chws[PMC_MCK] = hw;
|
||||
|
||||
hw = at91rm9200_clk_register_usb(regmap, "usbck", "pllbck", usb_div);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
parent_names[0] = slck_name;
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "pllack";
|
||||
parent_names[3] = "pllbck";
|
||||
for (i = 0; i < data->num_progck; i++) {
|
||||
char name[6];
|
||||
|
||||
snprintf(name, sizeof(name), "prog%d", i);
|
||||
|
||||
hw = at91_clk_register_programmable(regmap, name,
|
||||
parent_names, 4, i,
|
||||
&at91rm9200_programmable_layout);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
for (i = 0; i < data->num_sck; i++) {
|
||||
hw = at91_clk_register_system(regmap, data->sck[i].n,
|
||||
data->sck[i].p,
|
||||
data->sck[i].id);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9260_pmc->shws[data->sck[i].id] = hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < data->num_pck; i++) {
|
||||
hw = at91_clk_register_peripheral(regmap,
|
||||
data->pck[i].n,
|
||||
"masterck",
|
||||
data->pck[i].id);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9260_pmc->phws[data->pck[i].id] = hw;
|
||||
}
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91sam9260_pmc);
|
||||
|
||||
return;
|
||||
|
||||
err_free:
|
||||
pmc_data_free(at91sam9260_pmc);
|
||||
}
|
||||
|
||||
static void __init at91sam9260_pmc_setup(struct device_node *np)
|
||||
{
|
||||
at91sam926x_pmc_setup(np, &at91sam9260_data);
|
||||
}
|
||||
CLK_OF_DECLARE_DRIVER(at91sam9260_pmc, "atmel,at91sam9260-pmc",
|
||||
at91sam9260_pmc_setup);
|
||||
|
||||
static void __init at91sam9261_pmc_setup(struct device_node *np)
|
||||
{
|
||||
at91sam926x_pmc_setup(np, &at91sam9261_data);
|
||||
}
|
||||
CLK_OF_DECLARE_DRIVER(at91sam9261_pmc, "atmel,at91sam9261-pmc",
|
||||
at91sam9261_pmc_setup);
|
||||
|
||||
static void __init at91sam9263_pmc_setup(struct device_node *np)
|
||||
{
|
||||
at91sam926x_pmc_setup(np, &at91sam9263_data);
|
||||
}
|
||||
CLK_OF_DECLARE_DRIVER(at91sam9263_pmc, "atmel,at91sam9263-pmc",
|
||||
at91sam9263_pmc_setup);
|
||||
|
||||
static void __init at91sam9g20_pmc_setup(struct device_node *np)
|
||||
{
|
||||
at91sam926x_pmc_setup(np, &at91sam9g20_data);
|
||||
}
|
||||
CLK_OF_DECLARE_DRIVER(at91sam9g20_pmc, "atmel,at91sam9g20-pmc",
|
||||
at91sam9g20_pmc_setup);
|
171
drivers/clk/at91/at91sam9rl.c
Normal file
171
drivers/clk/at91/at91sam9rl.c
Normal file
@ -0,0 +1,171 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dt-bindings/clock/at91.h>
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
static const struct clk_master_characteristics sam9rl_mck_characteristics = {
|
||||
.output = { .min = 0, .max = 94000000 },
|
||||
.divisors = { 1, 2, 4, 0 },
|
||||
};
|
||||
|
||||
static u8 sam9rl_plla_out[] = { 0, 2 };
|
||||
|
||||
static struct clk_range sam9rl_plla_outputs[] = {
|
||||
{ .min = 80000000, .max = 200000000 },
|
||||
{ .min = 190000000, .max = 240000000 },
|
||||
};
|
||||
|
||||
static const struct clk_pll_characteristics sam9rl_plla_characteristics = {
|
||||
.input = { .min = 1000000, .max = 32000000 },
|
||||
.num_output = ARRAY_SIZE(sam9rl_plla_outputs),
|
||||
.output = sam9rl_plla_outputs,
|
||||
.out = sam9rl_plla_out,
|
||||
};
|
||||
|
||||
static const struct {
|
||||
char *n;
|
||||
char *p;
|
||||
u8 id;
|
||||
} at91sam9rl_systemck[] = {
|
||||
{ .n = "pck0", .p = "prog0", .id = 8 },
|
||||
{ .n = "pck1", .p = "prog1", .id = 9 },
|
||||
};
|
||||
|
||||
static const struct {
|
||||
char *n;
|
||||
u8 id;
|
||||
} at91sam9rl_periphck[] = {
|
||||
{ .n = "pioA_clk", .id = 2, },
|
||||
{ .n = "pioB_clk", .id = 3, },
|
||||
{ .n = "pioC_clk", .id = 4, },
|
||||
{ .n = "pioD_clk", .id = 5, },
|
||||
{ .n = "usart0_clk", .id = 6, },
|
||||
{ .n = "usart1_clk", .id = 7, },
|
||||
{ .n = "usart2_clk", .id = 8, },
|
||||
{ .n = "usart3_clk", .id = 9, },
|
||||
{ .n = "mci0_clk", .id = 10, },
|
||||
{ .n = "twi0_clk", .id = 11, },
|
||||
{ .n = "twi1_clk", .id = 12, },
|
||||
{ .n = "spi0_clk", .id = 13, },
|
||||
{ .n = "ssc0_clk", .id = 14, },
|
||||
{ .n = "ssc1_clk", .id = 15, },
|
||||
{ .n = "tc0_clk", .id = 16, },
|
||||
{ .n = "tc1_clk", .id = 17, },
|
||||
{ .n = "tc2_clk", .id = 18, },
|
||||
{ .n = "pwm_clk", .id = 19, },
|
||||
{ .n = "adc_clk", .id = 20, },
|
||||
{ .n = "dma0_clk", .id = 21, },
|
||||
{ .n = "udphs_clk", .id = 22, },
|
||||
{ .n = "lcd_clk", .id = 23, },
|
||||
};
|
||||
|
||||
static void __init at91sam9rl_pmc_setup(struct device_node *np)
|
||||
{
|
||||
const char *slck_name, *mainxtal_name;
|
||||
struct pmc_data *at91sam9rl_pmc;
|
||||
const char *parent_names[6];
|
||||
struct regmap *regmap;
|
||||
struct clk_hw *hw;
|
||||
int i;
|
||||
|
||||
i = of_property_match_string(np, "clock-names", "slow_clk");
|
||||
if (i < 0)
|
||||
return;
|
||||
|
||||
slck_name = of_clk_get_parent_name(np, i);
|
||||
|
||||
i = of_property_match_string(np, "clock-names", "main_xtal");
|
||||
if (i < 0)
|
||||
return;
|
||||
mainxtal_name = of_clk_get_parent_name(np, i);
|
||||
|
||||
regmap = syscon_node_to_regmap(np);
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
at91sam9rl_pmc = pmc_data_allocate(PMC_MAIN + 1,
|
||||
nck(at91sam9rl_systemck),
|
||||
nck(at91sam9rl_periphck), 0);
|
||||
if (!at91sam9rl_pmc)
|
||||
return;
|
||||
|
||||
hw = at91_clk_register_rm9200_main(regmap, "mainck", mainxtal_name);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9rl_pmc->chws[PMC_MAIN] = hw;
|
||||
|
||||
hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
|
||||
&at91rm9200_pll_layout,
|
||||
&sam9rl_plla_characteristics);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9rl_pmc->chws[PMC_UTMI] = hw;
|
||||
|
||||
parent_names[0] = slck_name;
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "pllack";
|
||||
parent_names[3] = "utmick";
|
||||
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
|
||||
&at91rm9200_master_layout,
|
||||
&sam9rl_mck_characteristics);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9rl_pmc->chws[PMC_MCK] = hw;
|
||||
|
||||
parent_names[0] = slck_name;
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "pllack";
|
||||
parent_names[3] = "utmick";
|
||||
parent_names[4] = "masterck";
|
||||
for (i = 0; i < 2; i++) {
|
||||
char name[6];
|
||||
|
||||
snprintf(name, sizeof(name), "prog%d", i);
|
||||
|
||||
hw = at91_clk_register_programmable(regmap, name,
|
||||
parent_names, 5, i,
|
||||
&at91rm9200_programmable_layout);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(at91sam9rl_systemck); i++) {
|
||||
hw = at91_clk_register_system(regmap, at91sam9rl_systemck[i].n,
|
||||
at91sam9rl_systemck[i].p,
|
||||
at91sam9rl_systemck[i].id);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9rl_pmc->shws[at91sam9rl_systemck[i].id] = hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(at91sam9rl_periphck); i++) {
|
||||
hw = at91_clk_register_peripheral(regmap,
|
||||
at91sam9rl_periphck[i].n,
|
||||
"masterck",
|
||||
at91sam9rl_periphck[i].id);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9rl_pmc->phws[at91sam9rl_periphck[i].id] = hw;
|
||||
}
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91sam9rl_pmc);
|
||||
|
||||
return;
|
||||
|
||||
err_free:
|
||||
pmc_data_free(at91sam9rl_pmc);
|
||||
}
|
||||
CLK_OF_DECLARE_DRIVER(at91sam9rl_pmc, "atmel,at91sam9rl-pmc", at91sam9rl_pmc_setup);
|
309
drivers/clk/at91/at91sam9x5.c
Normal file
309
drivers/clk/at91/at91sam9x5.c
Normal file
@ -0,0 +1,309 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dt-bindings/clock/at91.h>
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
static const struct clk_master_characteristics mck_characteristics = {
|
||||
.output = { .min = 0, .max = 133333333 },
|
||||
.divisors = { 1, 2, 4, 3 },
|
||||
.have_div3_pres = 1,
|
||||
};
|
||||
|
||||
static u8 plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 };
|
||||
|
||||
static u16 plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 };
|
||||
|
||||
static struct clk_range plla_outputs[] = {
|
||||
{ .min = 745000000, .max = 800000000 },
|
||||
{ .min = 695000000, .max = 750000000 },
|
||||
{ .min = 645000000, .max = 700000000 },
|
||||
{ .min = 595000000, .max = 650000000 },
|
||||
{ .min = 545000000, .max = 600000000 },
|
||||
{ .min = 495000000, .max = 555000000 },
|
||||
{ .min = 445000000, .max = 500000000 },
|
||||
{ .min = 400000000, .max = 450000000 },
|
||||
};
|
||||
|
||||
static const struct clk_pll_characteristics plla_characteristics = {
|
||||
.input = { .min = 2000000, .max = 32000000 },
|
||||
.num_output = ARRAY_SIZE(plla_outputs),
|
||||
.output = plla_outputs,
|
||||
.icpll = plla_icpll,
|
||||
.out = plla_out,
|
||||
};
|
||||
|
||||
static const struct {
|
||||
char *n;
|
||||
char *p;
|
||||
u8 id;
|
||||
} at91sam9x5_systemck[] = {
|
||||
{ .n = "ddrck", .p = "masterck", .id = 2 },
|
||||
{ .n = "smdck", .p = "smdclk", .id = 4 },
|
||||
{ .n = "uhpck", .p = "usbck", .id = 6 },
|
||||
{ .n = "udpck", .p = "usbck", .id = 7 },
|
||||
{ .n = "pck0", .p = "prog0", .id = 8 },
|
||||
{ .n = "pck1", .p = "prog1", .id = 9 },
|
||||
};
|
||||
|
||||
struct pck {
|
||||
char *n;
|
||||
u8 id;
|
||||
};
|
||||
|
||||
static const struct pck at91sam9x5_periphck[] = {
|
||||
{ .n = "pioAB_clk", .id = 2, },
|
||||
{ .n = "pioCD_clk", .id = 3, },
|
||||
{ .n = "smd_clk", .id = 4, },
|
||||
{ .n = "usart0_clk", .id = 5, },
|
||||
{ .n = "usart1_clk", .id = 6, },
|
||||
{ .n = "usart2_clk", .id = 7, },
|
||||
{ .n = "twi0_clk", .id = 9, },
|
||||
{ .n = "twi1_clk", .id = 10, },
|
||||
{ .n = "twi2_clk", .id = 11, },
|
||||
{ .n = "mci0_clk", .id = 12, },
|
||||
{ .n = "spi0_clk", .id = 13, },
|
||||
{ .n = "spi1_clk", .id = 14, },
|
||||
{ .n = "uart0_clk", .id = 15, },
|
||||
{ .n = "uart1_clk", .id = 16, },
|
||||
{ .n = "tcb0_clk", .id = 17, },
|
||||
{ .n = "pwm_clk", .id = 18, },
|
||||
{ .n = "adc_clk", .id = 19, },
|
||||
{ .n = "dma0_clk", .id = 20, },
|
||||
{ .n = "dma1_clk", .id = 21, },
|
||||
{ .n = "uhphs_clk", .id = 22, },
|
||||
{ .n = "udphs_clk", .id = 23, },
|
||||
{ .n = "mci1_clk", .id = 26, },
|
||||
{ .n = "ssc0_clk", .id = 28, },
|
||||
};
|
||||
|
||||
static const struct pck at91sam9g15_periphck[] = {
|
||||
{ .n = "lcdc_clk", .id = 25, },
|
||||
{ /* sentinel */}
|
||||
};
|
||||
|
||||
static const struct pck at91sam9g25_periphck[] = {
|
||||
{ .n = "usart3_clk", .id = 8, },
|
||||
{ .n = "macb0_clk", .id = 24, },
|
||||
{ .n = "isi_clk", .id = 25, },
|
||||
{ /* sentinel */}
|
||||
};
|
||||
|
||||
static const struct pck at91sam9g35_periphck[] = {
|
||||
{ .n = "macb0_clk", .id = 24, },
|
||||
{ .n = "lcdc_clk", .id = 25, },
|
||||
{ /* sentinel */}
|
||||
};
|
||||
|
||||
static const struct pck at91sam9x25_periphck[] = {
|
||||
{ .n = "usart3_clk", .id = 8, },
|
||||
{ .n = "macb0_clk", .id = 24, },
|
||||
{ .n = "macb1_clk", .id = 27, },
|
||||
{ .n = "can0_clk", .id = 29, },
|
||||
{ .n = "can1_clk", .id = 30, },
|
||||
{ /* sentinel */}
|
||||
};
|
||||
|
||||
static const struct pck at91sam9x35_periphck[] = {
|
||||
{ .n = "macb0_clk", .id = 24, },
|
||||
{ .n = "lcdc_clk", .id = 25, },
|
||||
{ .n = "can0_clk", .id = 29, },
|
||||
{ .n = "can1_clk", .id = 30, },
|
||||
{ /* sentinel */}
|
||||
};
|
||||
|
||||
static void __init at91sam9x5_pmc_setup(struct device_node *np,
|
||||
const struct pck *extra_pcks,
|
||||
bool has_lcdck)
|
||||
{
|
||||
struct clk_range range = CLK_RANGE(0, 0);
|
||||
const char *slck_name, *mainxtal_name;
|
||||
struct pmc_data *at91sam9x5_pmc;
|
||||
const char *parent_names[6];
|
||||
struct regmap *regmap;
|
||||
struct clk_hw *hw;
|
||||
int i;
|
||||
bool bypass;
|
||||
|
||||
i = of_property_match_string(np, "clock-names", "slow_clk");
|
||||
if (i < 0)
|
||||
return;
|
||||
|
||||
slck_name = of_clk_get_parent_name(np, i);
|
||||
|
||||
i = of_property_match_string(np, "clock-names", "main_xtal");
|
||||
if (i < 0)
|
||||
return;
|
||||
mainxtal_name = of_clk_get_parent_name(np, i);
|
||||
|
||||
regmap = syscon_node_to_regmap(np);
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
at91sam9x5_pmc = pmc_data_allocate(PMC_MAIN + 1,
|
||||
nck(at91sam9x5_systemck),
|
||||
nck(at91sam9x35_periphck), 0);
|
||||
if (!at91sam9x5_pmc)
|
||||
return;
|
||||
|
||||
hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
|
||||
50000000);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
bypass = of_property_read_bool(np, "atmel,osc-bypass");
|
||||
|
||||
hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
|
||||
bypass);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
parent_names[0] = "main_rc_osc";
|
||||
parent_names[1] = "main_osc";
|
||||
hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9x5_pmc->chws[PMC_MAIN] = hw;
|
||||
|
||||
hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
|
||||
&at91rm9200_pll_layout, &plla_characteristics);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_plldiv(regmap, "plladivck", "pllack");
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9x5_pmc->chws[PMC_UTMI] = hw;
|
||||
|
||||
parent_names[0] = slck_name;
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
parent_names[3] = "utmick";
|
||||
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
|
||||
&at91sam9x5_master_layout,
|
||||
&mck_characteristics);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9x5_pmc->chws[PMC_MCK] = hw;
|
||||
|
||||
parent_names[0] = "plladivck";
|
||||
parent_names[1] = "utmick";
|
||||
hw = at91sam9x5_clk_register_usb(regmap, "usbck", parent_names, 2);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91sam9x5_clk_register_smd(regmap, "smdclk", parent_names, 2);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
parent_names[0] = slck_name;
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
parent_names[3] = "utmick";
|
||||
parent_names[4] = "mck";
|
||||
for (i = 0; i < 2; i++) {
|
||||
char name[6];
|
||||
|
||||
snprintf(name, sizeof(name), "prog%d", i);
|
||||
|
||||
hw = at91_clk_register_programmable(regmap, name,
|
||||
parent_names, 5, i,
|
||||
&at91sam9x5_programmable_layout);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(at91sam9x5_systemck); i++) {
|
||||
hw = at91_clk_register_system(regmap, at91sam9x5_systemck[i].n,
|
||||
at91sam9x5_systemck[i].p,
|
||||
at91sam9x5_systemck[i].id);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9x5_pmc->shws[at91sam9x5_systemck[i].id] = hw;
|
||||
}
|
||||
|
||||
if (has_lcdck) {
|
||||
hw = at91_clk_register_system(regmap, "lcdck", "masterck", 3);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9x5_pmc->shws[3] = hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(at91sam9x5_periphck); i++) {
|
||||
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
|
||||
at91sam9x5_periphck[i].n,
|
||||
"masterck",
|
||||
at91sam9x5_periphck[i].id,
|
||||
&range);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9x5_pmc->phws[at91sam9x5_periphck[i].id] = hw;
|
||||
}
|
||||
|
||||
for (i = 0; extra_pcks[i].id; i++) {
|
||||
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
|
||||
extra_pcks[i].n,
|
||||
"masterck",
|
||||
extra_pcks[i].id,
|
||||
&range);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
at91sam9x5_pmc->phws[extra_pcks[i].id] = hw;
|
||||
}
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91sam9x5_pmc);
|
||||
|
||||
return;
|
||||
|
||||
err_free:
|
||||
pmc_data_free(at91sam9x5_pmc);
|
||||
}
|
||||
|
||||
static void __init at91sam9g15_pmc_setup(struct device_node *np)
|
||||
{
|
||||
at91sam9x5_pmc_setup(np, at91sam9g15_periphck, true);
|
||||
}
|
||||
CLK_OF_DECLARE_DRIVER(at91sam9g15_pmc, "atmel,at91sam9g15-pmc",
|
||||
at91sam9g15_pmc_setup);
|
||||
|
||||
static void __init at91sam9g25_pmc_setup(struct device_node *np)
|
||||
{
|
||||
at91sam9x5_pmc_setup(np, at91sam9g25_periphck, false);
|
||||
}
|
||||
CLK_OF_DECLARE_DRIVER(at91sam9g25_pmc, "atmel,at91sam9g25-pmc",
|
||||
at91sam9g25_pmc_setup);
|
||||
|
||||
static void __init at91sam9g35_pmc_setup(struct device_node *np)
|
||||
{
|
||||
at91sam9x5_pmc_setup(np, at91sam9g35_periphck, true);
|
||||
}
|
||||
CLK_OF_DECLARE_DRIVER(at91sam9g35_pmc, "atmel,at91sam9g35-pmc",
|
||||
at91sam9g35_pmc_setup);
|
||||
|
||||
static void __init at91sam9x25_pmc_setup(struct device_node *np)
|
||||
{
|
||||
at91sam9x5_pmc_setup(np, at91sam9x25_periphck, false);
|
||||
}
|
||||
CLK_OF_DECLARE_DRIVER(at91sam9x25_pmc, "atmel,at91sam9x25-pmc",
|
||||
at91sam9x25_pmc_setup);
|
||||
|
||||
static void __init at91sam9x35_pmc_setup(struct device_node *np)
|
||||
{
|
||||
at91sam9x5_pmc_setup(np, at91sam9x35_periphck, true);
|
||||
}
|
||||
CLK_OF_DECLARE_DRIVER(at91sam9x35_pmc, "atmel,at91sam9x35-pmc",
|
||||
at91sam9x35_pmc_setup);
|
@ -43,6 +43,8 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
#define AUDIO_PLL_DIV_FRAC BIT(22)
|
||||
#define AUDIO_PLL_ND_MAX (AT91_PMC_AUDIO_PLL_ND_MASK >> \
|
||||
AT91_PMC_AUDIO_PLL_ND_OFFSET)
|
||||
@ -444,93 +446,94 @@ static const struct clk_ops audio_pll_pmc_ops = {
|
||||
.set_rate = clk_audio_pll_pmc_set_rate,
|
||||
};
|
||||
|
||||
static int of_sama5d2_clk_audio_pll_setup(struct device_node *np,
|
||||
struct clk_init_data *init,
|
||||
struct clk_hw *hw,
|
||||
struct regmap **clk_audio_regmap)
|
||||
{
|
||||
struct regmap *regmap;
|
||||
const char *parent_names[1];
|
||||
int ret;
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
init->name = np->name;
|
||||
of_clk_parent_fill(np, parent_names, 1);
|
||||
init->parent_names = parent_names;
|
||||
init->num_parents = 1;
|
||||
|
||||
hw->init = init;
|
||||
*clk_audio_regmap = regmap;
|
||||
|
||||
ret = clk_hw_register(NULL, hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
|
||||
static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np)
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_audio_pll_frac(struct regmap *regmap, const char *name,
|
||||
const char *parent_name)
|
||||
{
|
||||
struct clk_audio_frac *frac_ck;
|
||||
struct clk_init_data init = {};
|
||||
int ret;
|
||||
|
||||
frac_ck = kzalloc(sizeof(*frac_ck), GFP_KERNEL);
|
||||
if (!frac_ck)
|
||||
return;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &audio_pll_frac_ops;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
init.flags = CLK_SET_RATE_GATE;
|
||||
|
||||
if (of_sama5d2_clk_audio_pll_setup(np, &init, &frac_ck->hw,
|
||||
&frac_ck->regmap))
|
||||
frac_ck->hw.init = &init;
|
||||
frac_ck->regmap = regmap;
|
||||
|
||||
ret = clk_hw_register(NULL, &frac_ck->hw);
|
||||
if (ret) {
|
||||
kfree(frac_ck);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return &frac_ck->hw;
|
||||
}
|
||||
|
||||
static void __init of_sama5d2_clk_audio_pll_pad_setup(struct device_node *np)
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_audio_pll_pad(struct regmap *regmap, const char *name,
|
||||
const char *parent_name)
|
||||
{
|
||||
struct clk_audio_pad *apad_ck;
|
||||
struct clk_init_data init = {};
|
||||
struct clk_init_data init;
|
||||
int ret;
|
||||
|
||||
apad_ck = kzalloc(sizeof(*apad_ck), GFP_KERNEL);
|
||||
if (!apad_ck)
|
||||
return;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &audio_pll_pad_ops;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
|
||||
CLK_SET_RATE_PARENT;
|
||||
|
||||
if (of_sama5d2_clk_audio_pll_setup(np, &init, &apad_ck->hw,
|
||||
&apad_ck->regmap))
|
||||
apad_ck->hw.init = &init;
|
||||
apad_ck->regmap = regmap;
|
||||
|
||||
ret = clk_hw_register(NULL, &apad_ck->hw);
|
||||
if (ret) {
|
||||
kfree(apad_ck);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return &apad_ck->hw;
|
||||
}
|
||||
|
||||
static void __init of_sama5d2_clk_audio_pll_pmc_setup(struct device_node *np)
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_audio_pll_pmc(struct regmap *regmap, const char *name,
|
||||
const char *parent_name)
|
||||
{
|
||||
struct clk_audio_pad *apmc_ck;
|
||||
struct clk_init_data init = {};
|
||||
struct clk_audio_pmc *apmc_ck;
|
||||
struct clk_init_data init;
|
||||
int ret;
|
||||
|
||||
apmc_ck = kzalloc(sizeof(*apmc_ck), GFP_KERNEL);
|
||||
if (!apmc_ck)
|
||||
return;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &audio_pll_pmc_ops;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
|
||||
CLK_SET_RATE_PARENT;
|
||||
|
||||
if (of_sama5d2_clk_audio_pll_setup(np, &init, &apmc_ck->hw,
|
||||
&apmc_ck->regmap))
|
||||
kfree(apmc_ck);
|
||||
}
|
||||
apmc_ck->hw.init = &init;
|
||||
apmc_ck->regmap = regmap;
|
||||
|
||||
CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_frac_setup,
|
||||
"atmel,sama5d2-clk-audio-pll-frac",
|
||||
of_sama5d2_clk_audio_pll_frac_setup);
|
||||
CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pad_setup,
|
||||
"atmel,sama5d2-clk-audio-pll-pad",
|
||||
of_sama5d2_clk_audio_pll_pad_setup);
|
||||
CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pmc_setup,
|
||||
"atmel,sama5d2-clk-audio-pll-pmc",
|
||||
of_sama5d2_clk_audio_pll_pmc_setup);
|
||||
ret = clk_hw_register(NULL, &apmc_ck->hw);
|
||||
if (ret) {
|
||||
kfree(apmc_ck);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return &apmc_ck->hw;
|
||||
}
|
||||
|
@ -20,17 +20,8 @@
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
#define PERIPHERAL_MAX 64
|
||||
#define PERIPHERAL_ID_MIN 2
|
||||
|
||||
#define GENERATED_SOURCE_MAX 6
|
||||
#define GENERATED_MAX_DIV 255
|
||||
|
||||
#define GCK_ID_SSC0 43
|
||||
#define GCK_ID_SSC1 44
|
||||
#define GCK_ID_I2S0 54
|
||||
#define GCK_ID_I2S1 55
|
||||
#define GCK_ID_CLASSD 59
|
||||
#define GCK_INDEX_DT_AUDIO_PLL 5
|
||||
|
||||
struct clk_generated {
|
||||
@ -279,10 +270,10 @@ static void clk_generated_startup(struct clk_generated *gck)
|
||||
>> AT91_PMC_PCR_GCKDIV_OFFSET;
|
||||
}
|
||||
|
||||
static struct clk_hw * __init
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
|
||||
const char *name, const char **parent_names,
|
||||
u8 num_parents, u8 id,
|
||||
u8 num_parents, u8 id, bool pll_audio,
|
||||
const struct clk_range *range)
|
||||
{
|
||||
struct clk_generated *gck;
|
||||
@ -306,6 +297,7 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
|
||||
gck->regmap = regmap;
|
||||
gck->lock = lock;
|
||||
gck->range = *range;
|
||||
gck->audio_pll_allowed = pll_audio;
|
||||
|
||||
clk_generated_startup(gck);
|
||||
hw = &gck->hw;
|
||||
@ -319,70 +311,3 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
static void __init of_sama5d2_clk_generated_setup(struct device_node *np)
|
||||
{
|
||||
int num;
|
||||
u32 id;
|
||||
const char *name;
|
||||
struct clk_hw *hw;
|
||||
unsigned int num_parents;
|
||||
const char *parent_names[GENERATED_SOURCE_MAX];
|
||||
struct device_node *gcknp;
|
||||
struct clk_range range = CLK_RANGE(0, 0);
|
||||
struct regmap *regmap;
|
||||
struct clk_generated *gck;
|
||||
|
||||
num_parents = of_clk_get_parent_count(np);
|
||||
if (num_parents == 0 || num_parents > GENERATED_SOURCE_MAX)
|
||||
return;
|
||||
|
||||
of_clk_parent_fill(np, parent_names, num_parents);
|
||||
|
||||
num = of_get_child_count(np);
|
||||
if (!num || num > PERIPHERAL_MAX)
|
||||
return;
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
for_each_child_of_node(np, gcknp) {
|
||||
if (of_property_read_u32(gcknp, "reg", &id))
|
||||
continue;
|
||||
|
||||
if (id < PERIPHERAL_ID_MIN || id >= PERIPHERAL_MAX)
|
||||
continue;
|
||||
|
||||
if (of_property_read_string(np, "clock-output-names", &name))
|
||||
name = gcknp->name;
|
||||
|
||||
of_at91_get_clk_range(gcknp, "atmel,clk-output-range",
|
||||
&range);
|
||||
|
||||
hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, name,
|
||||
parent_names, num_parents,
|
||||
id, &range);
|
||||
|
||||
gck = to_clk_generated(hw);
|
||||
|
||||
if (of_device_is_compatible(np,
|
||||
"atmel,sama5d2-clk-generated")) {
|
||||
if (gck->id == GCK_ID_SSC0 || gck->id == GCK_ID_SSC1 ||
|
||||
gck->id == GCK_ID_I2S0 || gck->id == GCK_ID_I2S1 ||
|
||||
gck->id == GCK_ID_CLASSD)
|
||||
gck->audio_pll_allowed = true;
|
||||
else
|
||||
gck->audio_pll_allowed = false;
|
||||
} else {
|
||||
gck->audio_pll_allowed = false;
|
||||
}
|
||||
|
||||
if (IS_ERR(hw))
|
||||
continue;
|
||||
|
||||
of_clk_add_hw_provider(gcknp, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
}
|
||||
CLK_OF_DECLARE(of_sama5d2_clk_generated_setup, "atmel,sama5d2-clk-generated",
|
||||
of_sama5d2_clk_generated_setup);
|
||||
|
@ -86,25 +86,19 @@ static const struct clk_ops h32mx_ops = {
|
||||
.set_rate = clk_sama5d4_h32mx_set_rate,
|
||||
};
|
||||
|
||||
static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np)
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_h32mx(struct regmap *regmap, const char *name,
|
||||
const char *parent_name)
|
||||
{
|
||||
struct clk_sama5d4_h32mx *h32mxclk;
|
||||
struct clk_init_data init;
|
||||
const char *parent_name;
|
||||
struct regmap *regmap;
|
||||
int ret;
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
h32mxclk = kzalloc(sizeof(*h32mxclk), GFP_KERNEL);
|
||||
if (!h32mxclk)
|
||||
return;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
|
||||
init.name = np->name;
|
||||
init.name = name;
|
||||
init.ops = &h32mx_ops;
|
||||
init.parent_names = parent_name ? &parent_name : NULL;
|
||||
init.num_parents = parent_name ? 1 : 0;
|
||||
@ -116,10 +110,8 @@ static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np)
|
||||
ret = clk_hw_register(NULL, &h32mxclk->hw);
|
||||
if (ret) {
|
||||
kfree(h32mxclk);
|
||||
return;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, &h32mxclk->hw);
|
||||
return &h32mxclk->hw;
|
||||
}
|
||||
CLK_OF_DECLARE(of_sama5d4_clk_h32mx_setup, "atmel,sama5d4-clk-h32mx",
|
||||
of_sama5d4_clk_h32mx_setup);
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
#include <soc/at91/atmel-sfr.h>
|
||||
|
||||
#define I2S_BUS_NR 2
|
||||
#include "pmc.h"
|
||||
|
||||
struct clk_i2s_mux {
|
||||
struct clk_hw hw;
|
||||
@ -48,7 +48,7 @@ static const struct clk_ops clk_i2s_mux_ops = {
|
||||
.determine_rate = __clk_mux_determine_rate,
|
||||
};
|
||||
|
||||
static struct clk_hw * __init
|
||||
struct clk_hw * __init
|
||||
at91_clk_i2s_mux_register(struct regmap *regmap, const char *name,
|
||||
const char * const *parent_names,
|
||||
unsigned int num_parents, u8 bus_id)
|
||||
@ -78,39 +78,3 @@ at91_clk_i2s_mux_register(struct regmap *regmap, const char *name,
|
||||
|
||||
return &i2s_ck->hw;
|
||||
}
|
||||
|
||||
static void __init of_sama5d2_clk_i2s_mux_setup(struct device_node *np)
|
||||
{
|
||||
struct regmap *regmap_sfr;
|
||||
u8 bus_id;
|
||||
const char *parent_names[2];
|
||||
struct device_node *i2s_mux_np;
|
||||
struct clk_hw *hw;
|
||||
int ret;
|
||||
|
||||
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
|
||||
if (IS_ERR(regmap_sfr))
|
||||
return;
|
||||
|
||||
for_each_child_of_node(np, i2s_mux_np) {
|
||||
if (of_property_read_u8(i2s_mux_np, "reg", &bus_id))
|
||||
continue;
|
||||
|
||||
if (bus_id > I2S_BUS_NR)
|
||||
continue;
|
||||
|
||||
ret = of_clk_parent_fill(i2s_mux_np, parent_names, 2);
|
||||
if (ret != 2)
|
||||
continue;
|
||||
|
||||
hw = at91_clk_i2s_mux_register(regmap_sfr, i2s_mux_np->name,
|
||||
parent_names, 2, bus_id);
|
||||
if (IS_ERR(hw))
|
||||
continue;
|
||||
|
||||
of_clk_add_hw_provider(i2s_mux_np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(sama5d2_clk_i2s_mux, "atmel,sama5d2-clk-i2s-mux",
|
||||
of_sama5d2_clk_i2s_mux_setup);
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/clk/at91_pmc.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
@ -128,7 +127,7 @@ static const struct clk_ops main_osc_ops = {
|
||||
.is_prepared = clk_main_osc_is_prepared,
|
||||
};
|
||||
|
||||
static struct clk_hw * __init
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_main_osc(struct regmap *regmap,
|
||||
const char *name,
|
||||
const char *parent_name,
|
||||
@ -171,31 +170,6 @@ at91_clk_register_main_osc(struct regmap *regmap,
|
||||
return hw;
|
||||
}
|
||||
|
||||
static void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
const char *name = np->name;
|
||||
const char *parent_name;
|
||||
struct regmap *regmap;
|
||||
bool bypass;
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
bypass = of_property_read_bool(np, "atmel,osc-bypass");
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
hw = at91_clk_register_main_osc(regmap, name, parent_name, bypass);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(at91rm9200_clk_main_osc, "atmel,at91rm9200-clk-main-osc",
|
||||
of_at91rm9200_clk_main_osc_setup);
|
||||
|
||||
static bool clk_main_rc_osc_ready(struct regmap *regmap)
|
||||
{
|
||||
unsigned int status;
|
||||
@ -275,7 +249,7 @@ static const struct clk_ops main_rc_osc_ops = {
|
||||
.recalc_accuracy = clk_main_rc_osc_recalc_accuracy,
|
||||
};
|
||||
|
||||
static struct clk_hw * __init
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_main_rc_osc(struct regmap *regmap,
|
||||
const char *name,
|
||||
u32 frequency, u32 accuracy)
|
||||
@ -313,32 +287,6 @@ at91_clk_register_main_rc_osc(struct regmap *regmap,
|
||||
return hw;
|
||||
}
|
||||
|
||||
static void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
u32 frequency = 0;
|
||||
u32 accuracy = 0;
|
||||
const char *name = np->name;
|
||||
struct regmap *regmap;
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
of_property_read_u32(np, "clock-frequency", &frequency);
|
||||
of_property_read_u32(np, "clock-accuracy", &accuracy);
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
hw = at91_clk_register_main_rc_osc(regmap, name, frequency, accuracy);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9x5_clk_main_rc_osc, "atmel,at91sam9x5-clk-main-rc-osc",
|
||||
of_at91sam9x5_clk_main_rc_osc_setup);
|
||||
|
||||
|
||||
static int clk_main_probe_frequency(struct regmap *regmap)
|
||||
{
|
||||
unsigned long prep_time, timeout;
|
||||
@ -403,7 +351,7 @@ static const struct clk_ops rm9200_main_ops = {
|
||||
.recalc_rate = clk_rm9200_main_recalc_rate,
|
||||
};
|
||||
|
||||
static struct clk_hw * __init
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_rm9200_main(struct regmap *regmap,
|
||||
const char *name,
|
||||
const char *parent_name)
|
||||
@ -442,29 +390,6 @@ at91_clk_register_rm9200_main(struct regmap *regmap,
|
||||
return hw;
|
||||
}
|
||||
|
||||
static void __init of_at91rm9200_clk_main_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
const char *parent_name;
|
||||
const char *name = np->name;
|
||||
struct regmap *regmap;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
hw = at91_clk_register_rm9200_main(regmap, name, parent_name);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(at91rm9200_clk_main, "atmel,at91rm9200-clk-main",
|
||||
of_at91rm9200_clk_main_setup);
|
||||
|
||||
static inline bool clk_sam9x5_main_ready(struct regmap *regmap)
|
||||
{
|
||||
unsigned int status;
|
||||
@ -541,7 +466,7 @@ static const struct clk_ops sam9x5_main_ops = {
|
||||
.get_parent = clk_sam9x5_main_get_parent,
|
||||
};
|
||||
|
||||
static struct clk_hw * __init
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_sam9x5_main(struct regmap *regmap,
|
||||
const char *name,
|
||||
const char **parent_names,
|
||||
@ -583,32 +508,3 @@ at91_clk_register_sam9x5_main(struct regmap *regmap,
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
static void __init of_at91sam9x5_clk_main_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
const char *parent_names[2];
|
||||
unsigned int num_parents;
|
||||
const char *name = np->name;
|
||||
struct regmap *regmap;
|
||||
|
||||
num_parents = of_clk_get_parent_count(np);
|
||||
if (num_parents == 0 || num_parents > 2)
|
||||
return;
|
||||
|
||||
of_clk_parent_fill(np, parent_names, num_parents);
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
hw = at91_clk_register_sam9x5_main(regmap, name, parent_names,
|
||||
num_parents);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9x5_clk_main, "atmel,at91sam9x5-clk-main",
|
||||
of_at91sam9x5_clk_main_setup);
|
||||
|
@ -17,24 +17,11 @@
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
#define MASTER_SOURCE_MAX 4
|
||||
|
||||
#define MASTER_PRES_MASK 0x7
|
||||
#define MASTER_PRES_MAX MASTER_PRES_MASK
|
||||
#define MASTER_DIV_SHIFT 8
|
||||
#define MASTER_DIV_MASK 0x3
|
||||
|
||||
struct clk_master_characteristics {
|
||||
struct clk_range output;
|
||||
u32 divisors[4];
|
||||
u8 have_div3_pres;
|
||||
};
|
||||
|
||||
struct clk_master_layout {
|
||||
u32 mask;
|
||||
u8 pres_shift;
|
||||
};
|
||||
|
||||
#define to_clk_master(hw) container_of(hw, struct clk_master, hw)
|
||||
|
||||
struct clk_master {
|
||||
@ -120,7 +107,7 @@ static const struct clk_ops master_ops = {
|
||||
.get_parent = clk_master_get_parent,
|
||||
};
|
||||
|
||||
static struct clk_hw * __init
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_master(struct regmap *regmap,
|
||||
const char *name, int num_parents,
|
||||
const char **parent_names,
|
||||
@ -161,92 +148,12 @@ at91_clk_register_master(struct regmap *regmap,
|
||||
}
|
||||
|
||||
|
||||
static const struct clk_master_layout at91rm9200_master_layout = {
|
||||
const struct clk_master_layout at91rm9200_master_layout = {
|
||||
.mask = 0x31F,
|
||||
.pres_shift = 2,
|
||||
};
|
||||
|
||||
static const struct clk_master_layout at91sam9x5_master_layout = {
|
||||
const struct clk_master_layout at91sam9x5_master_layout = {
|
||||
.mask = 0x373,
|
||||
.pres_shift = 4,
|
||||
};
|
||||
|
||||
|
||||
static struct clk_master_characteristics * __init
|
||||
of_at91_clk_master_get_characteristics(struct device_node *np)
|
||||
{
|
||||
struct clk_master_characteristics *characteristics;
|
||||
|
||||
characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
|
||||
if (!characteristics)
|
||||
return NULL;
|
||||
|
||||
if (of_at91_get_clk_range(np, "atmel,clk-output-range", &characteristics->output))
|
||||
goto out_free_characteristics;
|
||||
|
||||
of_property_read_u32_array(np, "atmel,clk-divisors",
|
||||
characteristics->divisors, 4);
|
||||
|
||||
characteristics->have_div3_pres =
|
||||
of_property_read_bool(np, "atmel,master-clk-have-div3-pres");
|
||||
|
||||
return characteristics;
|
||||
|
||||
out_free_characteristics:
|
||||
kfree(characteristics);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void __init
|
||||
of_at91_clk_master_setup(struct device_node *np,
|
||||
const struct clk_master_layout *layout)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
unsigned int num_parents;
|
||||
const char *parent_names[MASTER_SOURCE_MAX];
|
||||
const char *name = np->name;
|
||||
struct clk_master_characteristics *characteristics;
|
||||
struct regmap *regmap;
|
||||
|
||||
num_parents = of_clk_get_parent_count(np);
|
||||
if (num_parents == 0 || num_parents > MASTER_SOURCE_MAX)
|
||||
return;
|
||||
|
||||
of_clk_parent_fill(np, parent_names, num_parents);
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
characteristics = of_at91_clk_master_get_characteristics(np);
|
||||
if (!characteristics)
|
||||
return;
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
hw = at91_clk_register_master(regmap, name, num_parents,
|
||||
parent_names, layout,
|
||||
characteristics);
|
||||
if (IS_ERR(hw))
|
||||
goto out_free_characteristics;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
return;
|
||||
|
||||
out_free_characteristics:
|
||||
kfree(characteristics);
|
||||
}
|
||||
|
||||
static void __init of_at91rm9200_clk_master_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_master_setup(np, &at91rm9200_master_layout);
|
||||
}
|
||||
CLK_OF_DECLARE(at91rm9200_clk_master, "atmel,at91rm9200-clk-master",
|
||||
of_at91rm9200_clk_master_setup);
|
||||
|
||||
static void __init of_at91sam9x5_clk_master_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_master_setup(np, &at91sam9x5_master_layout);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9x5_clk_master, "atmel,at91sam9x5-clk-master",
|
||||
of_at91sam9x5_clk_master_setup);
|
||||
|
@ -19,11 +19,6 @@
|
||||
|
||||
DEFINE_SPINLOCK(pmc_pcr_lock);
|
||||
|
||||
#define PERIPHERAL_MAX 64
|
||||
|
||||
#define PERIPHERAL_AT91RM9200 0
|
||||
#define PERIPHERAL_AT91SAM9X5 1
|
||||
|
||||
#define PERIPHERAL_ID_MIN 2
|
||||
#define PERIPHERAL_ID_MAX 31
|
||||
#define PERIPHERAL_MASK(id) (1 << ((id) & PERIPHERAL_ID_MAX))
|
||||
@ -104,7 +99,7 @@ static const struct clk_ops peripheral_ops = {
|
||||
.is_enabled = clk_peripheral_is_enabled,
|
||||
};
|
||||
|
||||
static struct clk_hw * __init
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_peripheral(struct regmap *regmap, const char *name,
|
||||
const char *parent_name, u32 id)
|
||||
{
|
||||
@ -331,7 +326,7 @@ static const struct clk_ops sam9x5_peripheral_ops = {
|
||||
.set_rate = clk_sam9x5_peripheral_set_rate,
|
||||
};
|
||||
|
||||
static struct clk_hw * __init
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
|
||||
const char *name, const char *parent_name,
|
||||
u32 id, const struct clk_range *range)
|
||||
@ -374,75 +369,3 @@ at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
static void __init
|
||||
of_at91_clk_periph_setup(struct device_node *np, u8 type)
|
||||
{
|
||||
int num;
|
||||
u32 id;
|
||||
struct clk_hw *hw;
|
||||
const char *parent_name;
|
||||
const char *name;
|
||||
struct device_node *periphclknp;
|
||||
struct regmap *regmap;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
if (!parent_name)
|
||||
return;
|
||||
|
||||
num = of_get_child_count(np);
|
||||
if (!num || num > PERIPHERAL_MAX)
|
||||
return;
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
for_each_child_of_node(np, periphclknp) {
|
||||
if (of_property_read_u32(periphclknp, "reg", &id))
|
||||
continue;
|
||||
|
||||
if (id >= PERIPHERAL_MAX)
|
||||
continue;
|
||||
|
||||
if (of_property_read_string(np, "clock-output-names", &name))
|
||||
name = periphclknp->name;
|
||||
|
||||
if (type == PERIPHERAL_AT91RM9200) {
|
||||
hw = at91_clk_register_peripheral(regmap, name,
|
||||
parent_name, id);
|
||||
} else {
|
||||
struct clk_range range = CLK_RANGE(0, 0);
|
||||
|
||||
of_at91_get_clk_range(periphclknp,
|
||||
"atmel,clk-output-range",
|
||||
&range);
|
||||
|
||||
hw = at91_clk_register_sam9x5_peripheral(regmap,
|
||||
&pmc_pcr_lock,
|
||||
name,
|
||||
parent_name,
|
||||
id, &range);
|
||||
}
|
||||
|
||||
if (IS_ERR(hw))
|
||||
continue;
|
||||
|
||||
of_clk_add_hw_provider(periphclknp, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
}
|
||||
|
||||
static void __init of_at91rm9200_clk_periph_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_periph_setup(np, PERIPHERAL_AT91RM9200);
|
||||
}
|
||||
CLK_OF_DECLARE(at91rm9200_clk_periph, "atmel,at91rm9200-clk-peripheral",
|
||||
of_at91rm9200_clk_periph_setup);
|
||||
|
||||
static void __init of_at91sam9x5_clk_periph_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_periph_setup(np, PERIPHERAL_AT91SAM9X5);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9x5_clk_periph, "atmel,at91sam9x5-clk-peripheral",
|
||||
of_at91sam9x5_clk_periph_setup);
|
||||
|
||||
|
@ -34,20 +34,6 @@
|
||||
#define PLL_OUT_SHIFT 14
|
||||
#define PLL_MAX_ID 1
|
||||
|
||||
struct clk_pll_characteristics {
|
||||
struct clk_range input;
|
||||
int num_output;
|
||||
struct clk_range *output;
|
||||
u16 *icpll;
|
||||
u8 *out;
|
||||
};
|
||||
|
||||
struct clk_pll_layout {
|
||||
u32 pllr_mask;
|
||||
u16 mul_mask;
|
||||
u8 mul_shift;
|
||||
};
|
||||
|
||||
#define to_clk_pll(hw) container_of(hw, struct clk_pll, hw)
|
||||
|
||||
struct clk_pll {
|
||||
@ -288,7 +274,7 @@ static const struct clk_ops pll_ops = {
|
||||
.set_rate = clk_pll_set_rate,
|
||||
};
|
||||
|
||||
static struct clk_hw * __init
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_pll(struct regmap *regmap, const char *name,
|
||||
const char *parent_name, u8 id,
|
||||
const struct clk_pll_layout *layout,
|
||||
@ -334,189 +320,26 @@ at91_clk_register_pll(struct regmap *regmap, const char *name,
|
||||
}
|
||||
|
||||
|
||||
static const struct clk_pll_layout at91rm9200_pll_layout = {
|
||||
const struct clk_pll_layout at91rm9200_pll_layout = {
|
||||
.pllr_mask = 0x7FFFFFF,
|
||||
.mul_shift = 16,
|
||||
.mul_mask = 0x7FF,
|
||||
};
|
||||
|
||||
static const struct clk_pll_layout at91sam9g45_pll_layout = {
|
||||
const struct clk_pll_layout at91sam9g45_pll_layout = {
|
||||
.pllr_mask = 0xFFFFFF,
|
||||
.mul_shift = 16,
|
||||
.mul_mask = 0xFF,
|
||||
};
|
||||
|
||||
static const struct clk_pll_layout at91sam9g20_pllb_layout = {
|
||||
const struct clk_pll_layout at91sam9g20_pllb_layout = {
|
||||
.pllr_mask = 0x3FFFFF,
|
||||
.mul_shift = 16,
|
||||
.mul_mask = 0x3F,
|
||||
};
|
||||
|
||||
static const struct clk_pll_layout sama5d3_pll_layout = {
|
||||
const struct clk_pll_layout sama5d3_pll_layout = {
|
||||
.pllr_mask = 0x1FFFFFF,
|
||||
.mul_shift = 18,
|
||||
.mul_mask = 0x7F,
|
||||
};
|
||||
|
||||
|
||||
static struct clk_pll_characteristics * __init
|
||||
of_at91_clk_pll_get_characteristics(struct device_node *np)
|
||||
{
|
||||
int i;
|
||||
int offset;
|
||||
u32 tmp;
|
||||
int num_output;
|
||||
u32 num_cells;
|
||||
struct clk_range input;
|
||||
struct clk_range *output;
|
||||
u8 *out = NULL;
|
||||
u16 *icpll = NULL;
|
||||
struct clk_pll_characteristics *characteristics;
|
||||
|
||||
if (of_at91_get_clk_range(np, "atmel,clk-input-range", &input))
|
||||
return NULL;
|
||||
|
||||
if (of_property_read_u32(np, "#atmel,pll-clk-output-range-cells",
|
||||
&num_cells))
|
||||
return NULL;
|
||||
|
||||
if (num_cells < 2 || num_cells > 4)
|
||||
return NULL;
|
||||
|
||||
if (!of_get_property(np, "atmel,pll-clk-output-ranges", &tmp))
|
||||
return NULL;
|
||||
num_output = tmp / (sizeof(u32) * num_cells);
|
||||
|
||||
characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
|
||||
if (!characteristics)
|
||||
return NULL;
|
||||
|
||||
output = kcalloc(num_output, sizeof(*output), GFP_KERNEL);
|
||||
if (!output)
|
||||
goto out_free_characteristics;
|
||||
|
||||
if (num_cells > 2) {
|
||||
out = kcalloc(num_output, sizeof(*out), GFP_KERNEL);
|
||||
if (!out)
|
||||
goto out_free_output;
|
||||
}
|
||||
|
||||
if (num_cells > 3) {
|
||||
icpll = kcalloc(num_output, sizeof(*icpll), GFP_KERNEL);
|
||||
if (!icpll)
|
||||
goto out_free_output;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_output; i++) {
|
||||
offset = i * num_cells;
|
||||
if (of_property_read_u32_index(np,
|
||||
"atmel,pll-clk-output-ranges",
|
||||
offset, &tmp))
|
||||
goto out_free_output;
|
||||
output[i].min = tmp;
|
||||
if (of_property_read_u32_index(np,
|
||||
"atmel,pll-clk-output-ranges",
|
||||
offset + 1, &tmp))
|
||||
goto out_free_output;
|
||||
output[i].max = tmp;
|
||||
|
||||
if (num_cells == 2)
|
||||
continue;
|
||||
|
||||
if (of_property_read_u32_index(np,
|
||||
"atmel,pll-clk-output-ranges",
|
||||
offset + 2, &tmp))
|
||||
goto out_free_output;
|
||||
out[i] = tmp;
|
||||
|
||||
if (num_cells == 3)
|
||||
continue;
|
||||
|
||||
if (of_property_read_u32_index(np,
|
||||
"atmel,pll-clk-output-ranges",
|
||||
offset + 3, &tmp))
|
||||
goto out_free_output;
|
||||
icpll[i] = tmp;
|
||||
}
|
||||
|
||||
characteristics->input = input;
|
||||
characteristics->num_output = num_output;
|
||||
characteristics->output = output;
|
||||
characteristics->out = out;
|
||||
characteristics->icpll = icpll;
|
||||
return characteristics;
|
||||
|
||||
out_free_output:
|
||||
kfree(icpll);
|
||||
kfree(out);
|
||||
kfree(output);
|
||||
out_free_characteristics:
|
||||
kfree(characteristics);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void __init
|
||||
of_at91_clk_pll_setup(struct device_node *np,
|
||||
const struct clk_pll_layout *layout)
|
||||
{
|
||||
u32 id;
|
||||
struct clk_hw *hw;
|
||||
struct regmap *regmap;
|
||||
const char *parent_name;
|
||||
const char *name = np->name;
|
||||
struct clk_pll_characteristics *characteristics;
|
||||
|
||||
if (of_property_read_u32(np, "reg", &id))
|
||||
return;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
characteristics = of_at91_clk_pll_get_characteristics(np);
|
||||
if (!characteristics)
|
||||
return;
|
||||
|
||||
hw = at91_clk_register_pll(regmap, name, parent_name, id, layout,
|
||||
characteristics);
|
||||
if (IS_ERR(hw))
|
||||
goto out_free_characteristics;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
return;
|
||||
|
||||
out_free_characteristics:
|
||||
kfree(characteristics);
|
||||
}
|
||||
|
||||
static void __init of_at91rm9200_clk_pll_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_pll_setup(np, &at91rm9200_pll_layout);
|
||||
}
|
||||
CLK_OF_DECLARE(at91rm9200_clk_pll, "atmel,at91rm9200-clk-pll",
|
||||
of_at91rm9200_clk_pll_setup);
|
||||
|
||||
static void __init of_at91sam9g45_clk_pll_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_pll_setup(np, &at91sam9g45_pll_layout);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9g45_clk_pll, "atmel,at91sam9g45-clk-pll",
|
||||
of_at91sam9g45_clk_pll_setup);
|
||||
|
||||
static void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_pll_setup(np, &at91sam9g20_pllb_layout);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9g20_clk_pllb, "atmel,at91sam9g20-clk-pllb",
|
||||
of_at91sam9g20_clk_pllb_setup);
|
||||
|
||||
static void __init of_sama5d3_clk_pll_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_pll_setup(np, &sama5d3_pll_layout);
|
||||
}
|
||||
CLK_OF_DECLARE(sama5d3_clk_pll, "atmel,sama5d3-clk-pll",
|
||||
of_sama5d3_clk_pll_setup);
|
||||
|
@ -75,7 +75,7 @@ static const struct clk_ops plldiv_ops = {
|
||||
.set_rate = clk_plldiv_set_rate,
|
||||
};
|
||||
|
||||
static struct clk_hw * __init
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_plldiv(struct regmap *regmap, const char *name,
|
||||
const char *parent_name)
|
||||
{
|
||||
@ -106,28 +106,3 @@ at91_clk_register_plldiv(struct regmap *regmap, const char *name,
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
static void __init
|
||||
of_at91sam9x5_clk_plldiv_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
const char *parent_name;
|
||||
const char *name = np->name;
|
||||
struct regmap *regmap;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
hw = at91_clk_register_plldiv(regmap, name, parent_name);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9x5_clk_plldiv, "atmel,at91sam9x5-clk-plldiv",
|
||||
of_at91sam9x5_clk_plldiv_setup);
|
||||
|
@ -17,7 +17,6 @@
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
#define PROG_SOURCE_MAX 5
|
||||
#define PROG_ID_MAX 7
|
||||
|
||||
#define PROG_STATUS_MASK(id) (1 << ((id) + 8))
|
||||
@ -25,12 +24,6 @@
|
||||
#define PROG_PRES(layout, pckr) ((pckr >> layout->pres_shift) & PROG_PRES_MASK)
|
||||
#define PROG_MAX_RM9200_CSS 3
|
||||
|
||||
struct clk_programmable_layout {
|
||||
u8 pres_shift;
|
||||
u8 css_mask;
|
||||
u8 have_slck_mck;
|
||||
};
|
||||
|
||||
struct clk_programmable {
|
||||
struct clk_hw hw;
|
||||
struct regmap *regmap;
|
||||
@ -170,7 +163,7 @@ static const struct clk_ops programmable_ops = {
|
||||
.set_rate = clk_programmable_set_rate,
|
||||
};
|
||||
|
||||
static struct clk_hw * __init
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_programmable(struct regmap *regmap,
|
||||
const char *name, const char **parent_names,
|
||||
u8 num_parents, u8 id,
|
||||
@ -211,86 +204,20 @@ at91_clk_register_programmable(struct regmap *regmap,
|
||||
return hw;
|
||||
}
|
||||
|
||||
static const struct clk_programmable_layout at91rm9200_programmable_layout = {
|
||||
const struct clk_programmable_layout at91rm9200_programmable_layout = {
|
||||
.pres_shift = 2,
|
||||
.css_mask = 0x3,
|
||||
.have_slck_mck = 0,
|
||||
};
|
||||
|
||||
static const struct clk_programmable_layout at91sam9g45_programmable_layout = {
|
||||
const struct clk_programmable_layout at91sam9g45_programmable_layout = {
|
||||
.pres_shift = 2,
|
||||
.css_mask = 0x3,
|
||||
.have_slck_mck = 1,
|
||||
};
|
||||
|
||||
static const struct clk_programmable_layout at91sam9x5_programmable_layout = {
|
||||
const struct clk_programmable_layout at91sam9x5_programmable_layout = {
|
||||
.pres_shift = 4,
|
||||
.css_mask = 0x7,
|
||||
.have_slck_mck = 0,
|
||||
};
|
||||
|
||||
static void __init
|
||||
of_at91_clk_prog_setup(struct device_node *np,
|
||||
const struct clk_programmable_layout *layout)
|
||||
{
|
||||
int num;
|
||||
u32 id;
|
||||
struct clk_hw *hw;
|
||||
unsigned int num_parents;
|
||||
const char *parent_names[PROG_SOURCE_MAX];
|
||||
const char *name;
|
||||
struct device_node *progclknp;
|
||||
struct regmap *regmap;
|
||||
|
||||
num_parents = of_clk_get_parent_count(np);
|
||||
if (num_parents == 0 || num_parents > PROG_SOURCE_MAX)
|
||||
return;
|
||||
|
||||
of_clk_parent_fill(np, parent_names, num_parents);
|
||||
|
||||
num = of_get_child_count(np);
|
||||
if (!num || num > (PROG_ID_MAX + 1))
|
||||
return;
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
for_each_child_of_node(np, progclknp) {
|
||||
if (of_property_read_u32(progclknp, "reg", &id))
|
||||
continue;
|
||||
|
||||
if (of_property_read_string(np, "clock-output-names", &name))
|
||||
name = progclknp->name;
|
||||
|
||||
hw = at91_clk_register_programmable(regmap, name,
|
||||
parent_names, num_parents,
|
||||
id, layout);
|
||||
if (IS_ERR(hw))
|
||||
continue;
|
||||
|
||||
of_clk_add_hw_provider(progclknp, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void __init of_at91rm9200_clk_prog_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_prog_setup(np, &at91rm9200_programmable_layout);
|
||||
}
|
||||
CLK_OF_DECLARE(at91rm9200_clk_prog, "atmel,at91rm9200-clk-programmable",
|
||||
of_at91rm9200_clk_prog_setup);
|
||||
|
||||
static void __init of_at91sam9g45_clk_prog_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_prog_setup(np, &at91sam9g45_programmable_layout);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9g45_clk_prog, "atmel,at91sam9g45-clk-programmable",
|
||||
of_at91sam9g45_clk_prog_setup);
|
||||
|
||||
static void __init of_at91sam9x5_clk_prog_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_prog_setup(np, &at91sam9x5_programmable_layout);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9x5_clk_prog, "atmel,at91sam9x5-clk-programmable",
|
||||
of_at91sam9x5_clk_prog_setup);
|
||||
|
@ -40,7 +40,7 @@ static const struct clk_ops sam9260_slow_ops = {
|
||||
.get_parent = clk_sam9260_slow_get_parent,
|
||||
};
|
||||
|
||||
static struct clk_hw * __init
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_sam9260_slow(struct regmap *regmap,
|
||||
const char *name,
|
||||
const char **parent_names,
|
||||
@ -79,33 +79,3 @@ at91_clk_register_sam9260_slow(struct regmap *regmap,
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
static void __init of_at91sam9260_clk_slow_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
const char *parent_names[2];
|
||||
unsigned int num_parents;
|
||||
const char *name = np->name;
|
||||
struct regmap *regmap;
|
||||
|
||||
num_parents = of_clk_get_parent_count(np);
|
||||
if (num_parents != 2)
|
||||
return;
|
||||
|
||||
of_clk_parent_fill(np, parent_names, num_parents);
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
hw = at91_clk_register_sam9260_slow(regmap, name, parent_names,
|
||||
num_parents);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(at91sam9260_clk_slow, "atmel,at91sam9260-clk-slow",
|
||||
of_at91sam9260_clk_slow_setup);
|
||||
|
@ -17,8 +17,6 @@
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
#define SMD_SOURCE_MAX 2
|
||||
|
||||
#define SMD_DIV_SHIFT 8
|
||||
#define SMD_MAX_DIV 0xf
|
||||
|
||||
@ -111,7 +109,7 @@ static const struct clk_ops at91sam9x5_smd_ops = {
|
||||
.set_rate = at91sam9x5_clk_smd_set_rate,
|
||||
};
|
||||
|
||||
static struct clk_hw * __init
|
||||
struct clk_hw * __init
|
||||
at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name,
|
||||
const char **parent_names, u8 num_parents)
|
||||
{
|
||||
@ -142,33 +140,3 @@ at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name,
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
static void __init of_at91sam9x5_clk_smd_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
unsigned int num_parents;
|
||||
const char *parent_names[SMD_SOURCE_MAX];
|
||||
const char *name = np->name;
|
||||
struct regmap *regmap;
|
||||
|
||||
num_parents = of_clk_get_parent_count(np);
|
||||
if (num_parents == 0 || num_parents > SMD_SOURCE_MAX)
|
||||
return;
|
||||
|
||||
of_clk_parent_fill(np, parent_names, num_parents);
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
hw = at91sam9x5_clk_register_smd(regmap, name, parent_names,
|
||||
num_parents);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9x5_clk_smd, "atmel,at91sam9x5-clk-smd",
|
||||
of_at91sam9x5_clk_smd_setup);
|
||||
|
@ -88,7 +88,7 @@ static const struct clk_ops system_ops = {
|
||||
.is_prepared = clk_system_is_prepared,
|
||||
};
|
||||
|
||||
static struct clk_hw * __init
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_system(struct regmap *regmap, const char *name,
|
||||
const char *parent_name, u8 id)
|
||||
{
|
||||
@ -123,40 +123,3 @@ at91_clk_register_system(struct regmap *regmap, const char *name,
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
static void __init of_at91rm9200_clk_sys_setup(struct device_node *np)
|
||||
{
|
||||
int num;
|
||||
u32 id;
|
||||
struct clk_hw *hw;
|
||||
const char *name;
|
||||
struct device_node *sysclknp;
|
||||
const char *parent_name;
|
||||
struct regmap *regmap;
|
||||
|
||||
num = of_get_child_count(np);
|
||||
if (num > (SYSTEM_MAX_ID + 1))
|
||||
return;
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
for_each_child_of_node(np, sysclknp) {
|
||||
if (of_property_read_u32(sysclknp, "reg", &id))
|
||||
continue;
|
||||
|
||||
if (of_property_read_string(np, "clock-output-names", &name))
|
||||
name = sysclknp->name;
|
||||
|
||||
parent_name = of_clk_get_parent_name(sysclknp, 0);
|
||||
|
||||
hw = at91_clk_register_system(regmap, name, parent_name, id);
|
||||
if (IS_ERR(hw))
|
||||
continue;
|
||||
|
||||
of_clk_add_hw_provider(sysclknp, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
}
|
||||
CLK_OF_DECLARE(at91rm9200_clk_sys, "atmel,at91rm9200-clk-system",
|
||||
of_at91rm9200_clk_sys_setup);
|
||||
|
@ -17,8 +17,6 @@
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
#define USB_SOURCE_MAX 2
|
||||
|
||||
#define SAM9X5_USB_DIV_SHIFT 8
|
||||
#define SAM9X5_USB_MAX_DIV 0xf
|
||||
|
||||
@ -192,7 +190,7 @@ static const struct clk_ops at91sam9n12_usb_ops = {
|
||||
.set_rate = at91sam9x5_clk_usb_set_rate,
|
||||
};
|
||||
|
||||
static struct clk_hw * __init
|
||||
struct clk_hw * __init
|
||||
at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
|
||||
const char **parent_names, u8 num_parents)
|
||||
{
|
||||
@ -225,7 +223,7 @@ at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
|
||||
return hw;
|
||||
}
|
||||
|
||||
static struct clk_hw * __init
|
||||
struct clk_hw * __init
|
||||
at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name,
|
||||
const char *parent_name)
|
||||
{
|
||||
@ -342,7 +340,7 @@ static const struct clk_ops at91rm9200_usb_ops = {
|
||||
.set_rate = at91rm9200_clk_usb_set_rate,
|
||||
};
|
||||
|
||||
static struct clk_hw * __init
|
||||
struct clk_hw * __init
|
||||
at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
|
||||
const char *parent_name, const u32 *divisors)
|
||||
{
|
||||
@ -374,89 +372,3 @@ at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
static void __init of_at91sam9x5_clk_usb_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
unsigned int num_parents;
|
||||
const char *parent_names[USB_SOURCE_MAX];
|
||||
const char *name = np->name;
|
||||
struct regmap *regmap;
|
||||
|
||||
num_parents = of_clk_get_parent_count(np);
|
||||
if (num_parents == 0 || num_parents > USB_SOURCE_MAX)
|
||||
return;
|
||||
|
||||
of_clk_parent_fill(np, parent_names, num_parents);
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
hw = at91sam9x5_clk_register_usb(regmap, name, parent_names,
|
||||
num_parents);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9x5_clk_usb, "atmel,at91sam9x5-clk-usb",
|
||||
of_at91sam9x5_clk_usb_setup);
|
||||
|
||||
static void __init of_at91sam9n12_clk_usb_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
const char *parent_name;
|
||||
const char *name = np->name;
|
||||
struct regmap *regmap;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
if (!parent_name)
|
||||
return;
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
hw = at91sam9n12_clk_register_usb(regmap, name, parent_name);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9n12_clk_usb, "atmel,at91sam9n12-clk-usb",
|
||||
of_at91sam9n12_clk_usb_setup);
|
||||
|
||||
static void __init of_at91rm9200_clk_usb_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
const char *parent_name;
|
||||
const char *name = np->name;
|
||||
u32 divisors[4] = {0, 0, 0, 0};
|
||||
struct regmap *regmap;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
if (!parent_name)
|
||||
return;
|
||||
|
||||
of_property_read_u32_array(np, "atmel,clk-divisors", divisors, 4);
|
||||
if (!divisors[0])
|
||||
return;
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
hw = at91rm9200_clk_register_usb(regmap, name, parent_name, divisors);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(at91rm9200_clk_usb, "atmel,at91rm9200-clk-usb",
|
||||
of_at91rm9200_clk_usb_setup);
|
||||
|
@ -125,7 +125,7 @@ static const struct clk_ops utmi_ops = {
|
||||
.recalc_rate = clk_utmi_recalc_rate,
|
||||
};
|
||||
|
||||
static struct clk_hw * __init
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
|
||||
const char *name, const char *parent_name)
|
||||
{
|
||||
@ -157,46 +157,3 @@ at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
const char *parent_name;
|
||||
const char *name = np->name;
|
||||
struct regmap *regmap_pmc, *regmap_sfr;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
regmap_pmc = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap_pmc))
|
||||
return;
|
||||
|
||||
/*
|
||||
* If the device supports different mainck rates, this value has to be
|
||||
* set in the UTMI Clock Trimming register.
|
||||
* - 9x5: mainck supports several rates but it is indicated that a
|
||||
* 12 MHz is needed in case of USB.
|
||||
* - sama5d3 and sama5d2: mainck supports several rates. Configuring
|
||||
* the FREQ field of the UTMI Clock Trimming register is mandatory.
|
||||
* - sama5d4: mainck is at 12 MHz.
|
||||
*
|
||||
* We only need to retrieve sama5d3 or sama5d2 sfr regmap.
|
||||
*/
|
||||
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d3-sfr");
|
||||
if (IS_ERR(regmap_sfr)) {
|
||||
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
|
||||
if (IS_ERR(regmap_sfr))
|
||||
regmap_sfr = NULL;
|
||||
}
|
||||
|
||||
hw = at91_clk_register_utmi(regmap_pmc, regmap_sfr, name, parent_name);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
return;
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9x5_clk_utmi, "atmel,at91sam9x5-clk-utmi",
|
||||
of_at91sam9x5_clk_utmi_setup);
|
||||
|
961
drivers/clk/at91/dt-compat.c
Normal file
961
drivers/clk/at91/dt-compat.c
Normal file
@ -0,0 +1,961 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clk/at91_pmc.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
#define MASTER_SOURCE_MAX 4
|
||||
|
||||
#define PERIPHERAL_AT91RM9200 0
|
||||
#define PERIPHERAL_AT91SAM9X5 1
|
||||
|
||||
#define PERIPHERAL_MAX 64
|
||||
|
||||
#define PERIPHERAL_ID_MIN 2
|
||||
|
||||
#define PROG_SOURCE_MAX 5
|
||||
#define PROG_ID_MAX 7
|
||||
|
||||
#define SYSTEM_MAX_ID 31
|
||||
|
||||
#ifdef CONFIG_HAVE_AT91_AUDIO_PLL
|
||||
static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
const char *name = np->name;
|
||||
const char *parent_name;
|
||||
struct regmap *regmap;
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
|
||||
hw = at91_clk_register_audio_pll_frac(regmap, name, parent_name);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_frac_setup,
|
||||
"atmel,sama5d2-clk-audio-pll-frac",
|
||||
of_sama5d2_clk_audio_pll_frac_setup);
|
||||
|
||||
static void __init of_sama5d2_clk_audio_pll_pad_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
const char *name = np->name;
|
||||
const char *parent_name;
|
||||
struct regmap *regmap;
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
|
||||
hw = at91_clk_register_audio_pll_pad(regmap, name, parent_name);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pad_setup,
|
||||
"atmel,sama5d2-clk-audio-pll-pad",
|
||||
of_sama5d2_clk_audio_pll_pad_setup);
|
||||
|
||||
static void __init of_sama5d2_clk_audio_pll_pmc_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
const char *name = np->name;
|
||||
const char *parent_name;
|
||||
struct regmap *regmap;
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
|
||||
hw = at91_clk_register_audio_pll_pmc(regmap, name, parent_name);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pmc_setup,
|
||||
"atmel,sama5d2-clk-audio-pll-pmc",
|
||||
of_sama5d2_clk_audio_pll_pmc_setup);
|
||||
#endif /* CONFIG_HAVE_AT91_AUDIO_PLL */
|
||||
|
||||
#ifdef CONFIG_HAVE_AT91_GENERATED_CLK
|
||||
#define GENERATED_SOURCE_MAX 6
|
||||
|
||||
#define GCK_ID_I2S0 54
|
||||
#define GCK_ID_I2S1 55
|
||||
#define GCK_ID_CLASSD 59
|
||||
|
||||
static void __init of_sama5d2_clk_generated_setup(struct device_node *np)
|
||||
{
|
||||
int num;
|
||||
u32 id;
|
||||
const char *name;
|
||||
struct clk_hw *hw;
|
||||
unsigned int num_parents;
|
||||
const char *parent_names[GENERATED_SOURCE_MAX];
|
||||
struct device_node *gcknp;
|
||||
struct clk_range range = CLK_RANGE(0, 0);
|
||||
struct regmap *regmap;
|
||||
|
||||
num_parents = of_clk_get_parent_count(np);
|
||||
if (num_parents == 0 || num_parents > GENERATED_SOURCE_MAX)
|
||||
return;
|
||||
|
||||
of_clk_parent_fill(np, parent_names, num_parents);
|
||||
|
||||
num = of_get_child_count(np);
|
||||
if (!num || num > PERIPHERAL_MAX)
|
||||
return;
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
for_each_child_of_node(np, gcknp) {
|
||||
bool pll_audio = false;
|
||||
|
||||
if (of_property_read_u32(gcknp, "reg", &id))
|
||||
continue;
|
||||
|
||||
if (id < PERIPHERAL_ID_MIN || id >= PERIPHERAL_MAX)
|
||||
continue;
|
||||
|
||||
if (of_property_read_string(np, "clock-output-names", &name))
|
||||
name = gcknp->name;
|
||||
|
||||
of_at91_get_clk_range(gcknp, "atmel,clk-output-range",
|
||||
&range);
|
||||
|
||||
if (of_device_is_compatible(np, "atmel,sama5d2-clk-generated") &&
|
||||
(id == GCK_ID_I2S0 || id == GCK_ID_I2S1 ||
|
||||
id == GCK_ID_CLASSD))
|
||||
pll_audio = true;
|
||||
|
||||
hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, name,
|
||||
parent_names, num_parents,
|
||||
id, pll_audio, &range);
|
||||
if (IS_ERR(hw))
|
||||
continue;
|
||||
|
||||
of_clk_add_hw_provider(gcknp, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
}
|
||||
CLK_OF_DECLARE(of_sama5d2_clk_generated_setup, "atmel,sama5d2-clk-generated",
|
||||
of_sama5d2_clk_generated_setup);
|
||||
#endif /* CONFIG_HAVE_AT91_GENERATED_CLK */
|
||||
|
||||
#ifdef CONFIG_HAVE_AT91_H32MX
|
||||
static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
const char *name = np->name;
|
||||
const char *parent_name;
|
||||
struct regmap *regmap;
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
|
||||
hw = at91_clk_register_h32mx(regmap, name, parent_name);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(of_sama5d4_clk_h32mx_setup, "atmel,sama5d4-clk-h32mx",
|
||||
of_sama5d4_clk_h32mx_setup);
|
||||
#endif /* CONFIG_HAVE_AT91_H32MX */
|
||||
|
||||
#ifdef CONFIG_HAVE_AT91_I2S_MUX_CLK
|
||||
#define I2S_BUS_NR 2
|
||||
|
||||
static void __init of_sama5d2_clk_i2s_mux_setup(struct device_node *np)
|
||||
{
|
||||
struct regmap *regmap_sfr;
|
||||
u8 bus_id;
|
||||
const char *parent_names[2];
|
||||
struct device_node *i2s_mux_np;
|
||||
struct clk_hw *hw;
|
||||
int ret;
|
||||
|
||||
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
|
||||
if (IS_ERR(regmap_sfr))
|
||||
return;
|
||||
|
||||
for_each_child_of_node(np, i2s_mux_np) {
|
||||
if (of_property_read_u8(i2s_mux_np, "reg", &bus_id))
|
||||
continue;
|
||||
|
||||
if (bus_id > I2S_BUS_NR)
|
||||
continue;
|
||||
|
||||
ret = of_clk_parent_fill(i2s_mux_np, parent_names, 2);
|
||||
if (ret != 2)
|
||||
continue;
|
||||
|
||||
hw = at91_clk_i2s_mux_register(regmap_sfr, i2s_mux_np->name,
|
||||
parent_names, 2, bus_id);
|
||||
if (IS_ERR(hw))
|
||||
continue;
|
||||
|
||||
of_clk_add_hw_provider(i2s_mux_np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
}
|
||||
CLK_OF_DECLARE(sama5d2_clk_i2s_mux, "atmel,sama5d2-clk-i2s-mux",
|
||||
of_sama5d2_clk_i2s_mux_setup);
|
||||
#endif /* CONFIG_HAVE_AT91_I2S_MUX_CLK */
|
||||
|
||||
static void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
const char *name = np->name;
|
||||
const char *parent_name;
|
||||
struct regmap *regmap;
|
||||
bool bypass;
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
bypass = of_property_read_bool(np, "atmel,osc-bypass");
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
hw = at91_clk_register_main_osc(regmap, name, parent_name, bypass);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(at91rm9200_clk_main_osc, "atmel,at91rm9200-clk-main-osc",
|
||||
of_at91rm9200_clk_main_osc_setup);
|
||||
|
||||
static void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
u32 frequency = 0;
|
||||
u32 accuracy = 0;
|
||||
const char *name = np->name;
|
||||
struct regmap *regmap;
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
of_property_read_u32(np, "clock-frequency", &frequency);
|
||||
of_property_read_u32(np, "clock-accuracy", &accuracy);
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
hw = at91_clk_register_main_rc_osc(regmap, name, frequency, accuracy);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9x5_clk_main_rc_osc, "atmel,at91sam9x5-clk-main-rc-osc",
|
||||
of_at91sam9x5_clk_main_rc_osc_setup);
|
||||
|
||||
static void __init of_at91rm9200_clk_main_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
const char *parent_name;
|
||||
const char *name = np->name;
|
||||
struct regmap *regmap;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
hw = at91_clk_register_rm9200_main(regmap, name, parent_name);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(at91rm9200_clk_main, "atmel,at91rm9200-clk-main",
|
||||
of_at91rm9200_clk_main_setup);
|
||||
|
||||
static void __init of_at91sam9x5_clk_main_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
const char *parent_names[2];
|
||||
unsigned int num_parents;
|
||||
const char *name = np->name;
|
||||
struct regmap *regmap;
|
||||
|
||||
num_parents = of_clk_get_parent_count(np);
|
||||
if (num_parents == 0 || num_parents > 2)
|
||||
return;
|
||||
|
||||
of_clk_parent_fill(np, parent_names, num_parents);
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
hw = at91_clk_register_sam9x5_main(regmap, name, parent_names,
|
||||
num_parents);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9x5_clk_main, "atmel,at91sam9x5-clk-main",
|
||||
of_at91sam9x5_clk_main_setup);
|
||||
|
||||
static struct clk_master_characteristics * __init
|
||||
of_at91_clk_master_get_characteristics(struct device_node *np)
|
||||
{
|
||||
struct clk_master_characteristics *characteristics;
|
||||
|
||||
characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
|
||||
if (!characteristics)
|
||||
return NULL;
|
||||
|
||||
if (of_at91_get_clk_range(np, "atmel,clk-output-range", &characteristics->output))
|
||||
goto out_free_characteristics;
|
||||
|
||||
of_property_read_u32_array(np, "atmel,clk-divisors",
|
||||
characteristics->divisors, 4);
|
||||
|
||||
characteristics->have_div3_pres =
|
||||
of_property_read_bool(np, "atmel,master-clk-have-div3-pres");
|
||||
|
||||
return characteristics;
|
||||
|
||||
out_free_characteristics:
|
||||
kfree(characteristics);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void __init
|
||||
of_at91_clk_master_setup(struct device_node *np,
|
||||
const struct clk_master_layout *layout)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
unsigned int num_parents;
|
||||
const char *parent_names[MASTER_SOURCE_MAX];
|
||||
const char *name = np->name;
|
||||
struct clk_master_characteristics *characteristics;
|
||||
struct regmap *regmap;
|
||||
|
||||
num_parents = of_clk_get_parent_count(np);
|
||||
if (num_parents == 0 || num_parents > MASTER_SOURCE_MAX)
|
||||
return;
|
||||
|
||||
of_clk_parent_fill(np, parent_names, num_parents);
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
characteristics = of_at91_clk_master_get_characteristics(np);
|
||||
if (!characteristics)
|
||||
return;
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
hw = at91_clk_register_master(regmap, name, num_parents,
|
||||
parent_names, layout,
|
||||
characteristics);
|
||||
if (IS_ERR(hw))
|
||||
goto out_free_characteristics;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
return;
|
||||
|
||||
out_free_characteristics:
|
||||
kfree(characteristics);
|
||||
}
|
||||
|
||||
static void __init of_at91rm9200_clk_master_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_master_setup(np, &at91rm9200_master_layout);
|
||||
}
|
||||
CLK_OF_DECLARE(at91rm9200_clk_master, "atmel,at91rm9200-clk-master",
|
||||
of_at91rm9200_clk_master_setup);
|
||||
|
||||
static void __init of_at91sam9x5_clk_master_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_master_setup(np, &at91sam9x5_master_layout);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9x5_clk_master, "atmel,at91sam9x5-clk-master",
|
||||
of_at91sam9x5_clk_master_setup);
|
||||
|
||||
static void __init
|
||||
of_at91_clk_periph_setup(struct device_node *np, u8 type)
|
||||
{
|
||||
int num;
|
||||
u32 id;
|
||||
struct clk_hw *hw;
|
||||
const char *parent_name;
|
||||
const char *name;
|
||||
struct device_node *periphclknp;
|
||||
struct regmap *regmap;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
if (!parent_name)
|
||||
return;
|
||||
|
||||
num = of_get_child_count(np);
|
||||
if (!num || num > PERIPHERAL_MAX)
|
||||
return;
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
for_each_child_of_node(np, periphclknp) {
|
||||
if (of_property_read_u32(periphclknp, "reg", &id))
|
||||
continue;
|
||||
|
||||
if (id >= PERIPHERAL_MAX)
|
||||
continue;
|
||||
|
||||
if (of_property_read_string(np, "clock-output-names", &name))
|
||||
name = periphclknp->name;
|
||||
|
||||
if (type == PERIPHERAL_AT91RM9200) {
|
||||
hw = at91_clk_register_peripheral(regmap, name,
|
||||
parent_name, id);
|
||||
} else {
|
||||
struct clk_range range = CLK_RANGE(0, 0);
|
||||
|
||||
of_at91_get_clk_range(periphclknp,
|
||||
"atmel,clk-output-range",
|
||||
&range);
|
||||
|
||||
hw = at91_clk_register_sam9x5_peripheral(regmap,
|
||||
&pmc_pcr_lock,
|
||||
name,
|
||||
parent_name,
|
||||
id, &range);
|
||||
}
|
||||
|
||||
if (IS_ERR(hw))
|
||||
continue;
|
||||
|
||||
of_clk_add_hw_provider(periphclknp, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
}
|
||||
|
||||
static void __init of_at91rm9200_clk_periph_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_periph_setup(np, PERIPHERAL_AT91RM9200);
|
||||
}
|
||||
CLK_OF_DECLARE(at91rm9200_clk_periph, "atmel,at91rm9200-clk-peripheral",
|
||||
of_at91rm9200_clk_periph_setup);
|
||||
|
||||
static void __init of_at91sam9x5_clk_periph_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_periph_setup(np, PERIPHERAL_AT91SAM9X5);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9x5_clk_periph, "atmel,at91sam9x5-clk-peripheral",
|
||||
of_at91sam9x5_clk_periph_setup);
|
||||
|
||||
static struct clk_pll_characteristics * __init
|
||||
of_at91_clk_pll_get_characteristics(struct device_node *np)
|
||||
{
|
||||
int i;
|
||||
int offset;
|
||||
u32 tmp;
|
||||
int num_output;
|
||||
u32 num_cells;
|
||||
struct clk_range input;
|
||||
struct clk_range *output;
|
||||
u8 *out = NULL;
|
||||
u16 *icpll = NULL;
|
||||
struct clk_pll_characteristics *characteristics;
|
||||
|
||||
if (of_at91_get_clk_range(np, "atmel,clk-input-range", &input))
|
||||
return NULL;
|
||||
|
||||
if (of_property_read_u32(np, "#atmel,pll-clk-output-range-cells",
|
||||
&num_cells))
|
||||
return NULL;
|
||||
|
||||
if (num_cells < 2 || num_cells > 4)
|
||||
return NULL;
|
||||
|
||||
if (!of_get_property(np, "atmel,pll-clk-output-ranges", &tmp))
|
||||
return NULL;
|
||||
num_output = tmp / (sizeof(u32) * num_cells);
|
||||
|
||||
characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
|
||||
if (!characteristics)
|
||||
return NULL;
|
||||
|
||||
output = kcalloc(num_output, sizeof(*output), GFP_KERNEL);
|
||||
if (!output)
|
||||
goto out_free_characteristics;
|
||||
|
||||
if (num_cells > 2) {
|
||||
out = kcalloc(num_output, sizeof(*out), GFP_KERNEL);
|
||||
if (!out)
|
||||
goto out_free_output;
|
||||
}
|
||||
|
||||
if (num_cells > 3) {
|
||||
icpll = kcalloc(num_output, sizeof(*icpll), GFP_KERNEL);
|
||||
if (!icpll)
|
||||
goto out_free_output;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_output; i++) {
|
||||
offset = i * num_cells;
|
||||
if (of_property_read_u32_index(np,
|
||||
"atmel,pll-clk-output-ranges",
|
||||
offset, &tmp))
|
||||
goto out_free_output;
|
||||
output[i].min = tmp;
|
||||
if (of_property_read_u32_index(np,
|
||||
"atmel,pll-clk-output-ranges",
|
||||
offset + 1, &tmp))
|
||||
goto out_free_output;
|
||||
output[i].max = tmp;
|
||||
|
||||
if (num_cells == 2)
|
||||
continue;
|
||||
|
||||
if (of_property_read_u32_index(np,
|
||||
"atmel,pll-clk-output-ranges",
|
||||
offset + 2, &tmp))
|
||||
goto out_free_output;
|
||||
out[i] = tmp;
|
||||
|
||||
if (num_cells == 3)
|
||||
continue;
|
||||
|
||||
if (of_property_read_u32_index(np,
|
||||
"atmel,pll-clk-output-ranges",
|
||||
offset + 3, &tmp))
|
||||
goto out_free_output;
|
||||
icpll[i] = tmp;
|
||||
}
|
||||
|
||||
characteristics->input = input;
|
||||
characteristics->num_output = num_output;
|
||||
characteristics->output = output;
|
||||
characteristics->out = out;
|
||||
characteristics->icpll = icpll;
|
||||
return characteristics;
|
||||
|
||||
out_free_output:
|
||||
kfree(icpll);
|
||||
kfree(out);
|
||||
kfree(output);
|
||||
out_free_characteristics:
|
||||
kfree(characteristics);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void __init
|
||||
of_at91_clk_pll_setup(struct device_node *np,
|
||||
const struct clk_pll_layout *layout)
|
||||
{
|
||||
u32 id;
|
||||
struct clk_hw *hw;
|
||||
struct regmap *regmap;
|
||||
const char *parent_name;
|
||||
const char *name = np->name;
|
||||
struct clk_pll_characteristics *characteristics;
|
||||
|
||||
if (of_property_read_u32(np, "reg", &id))
|
||||
return;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
characteristics = of_at91_clk_pll_get_characteristics(np);
|
||||
if (!characteristics)
|
||||
return;
|
||||
|
||||
hw = at91_clk_register_pll(regmap, name, parent_name, id, layout,
|
||||
characteristics);
|
||||
if (IS_ERR(hw))
|
||||
goto out_free_characteristics;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
return;
|
||||
|
||||
out_free_characteristics:
|
||||
kfree(characteristics);
|
||||
}
|
||||
|
||||
static void __init of_at91rm9200_clk_pll_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_pll_setup(np, &at91rm9200_pll_layout);
|
||||
}
|
||||
CLK_OF_DECLARE(at91rm9200_clk_pll, "atmel,at91rm9200-clk-pll",
|
||||
of_at91rm9200_clk_pll_setup);
|
||||
|
||||
static void __init of_at91sam9g45_clk_pll_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_pll_setup(np, &at91sam9g45_pll_layout);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9g45_clk_pll, "atmel,at91sam9g45-clk-pll",
|
||||
of_at91sam9g45_clk_pll_setup);
|
||||
|
||||
static void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_pll_setup(np, &at91sam9g20_pllb_layout);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9g20_clk_pllb, "atmel,at91sam9g20-clk-pllb",
|
||||
of_at91sam9g20_clk_pllb_setup);
|
||||
|
||||
static void __init of_sama5d3_clk_pll_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_pll_setup(np, &sama5d3_pll_layout);
|
||||
}
|
||||
CLK_OF_DECLARE(sama5d3_clk_pll, "atmel,sama5d3-clk-pll",
|
||||
of_sama5d3_clk_pll_setup);
|
||||
|
||||
static void __init
|
||||
of_at91sam9x5_clk_plldiv_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
const char *parent_name;
|
||||
const char *name = np->name;
|
||||
struct regmap *regmap;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
hw = at91_clk_register_plldiv(regmap, name, parent_name);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9x5_clk_plldiv, "atmel,at91sam9x5-clk-plldiv",
|
||||
of_at91sam9x5_clk_plldiv_setup);
|
||||
|
||||
static void __init
|
||||
of_at91_clk_prog_setup(struct device_node *np,
|
||||
const struct clk_programmable_layout *layout)
|
||||
{
|
||||
int num;
|
||||
u32 id;
|
||||
struct clk_hw *hw;
|
||||
unsigned int num_parents;
|
||||
const char *parent_names[PROG_SOURCE_MAX];
|
||||
const char *name;
|
||||
struct device_node *progclknp;
|
||||
struct regmap *regmap;
|
||||
|
||||
num_parents = of_clk_get_parent_count(np);
|
||||
if (num_parents == 0 || num_parents > PROG_SOURCE_MAX)
|
||||
return;
|
||||
|
||||
of_clk_parent_fill(np, parent_names, num_parents);
|
||||
|
||||
num = of_get_child_count(np);
|
||||
if (!num || num > (PROG_ID_MAX + 1))
|
||||
return;
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
for_each_child_of_node(np, progclknp) {
|
||||
if (of_property_read_u32(progclknp, "reg", &id))
|
||||
continue;
|
||||
|
||||
if (of_property_read_string(np, "clock-output-names", &name))
|
||||
name = progclknp->name;
|
||||
|
||||
hw = at91_clk_register_programmable(regmap, name,
|
||||
parent_names, num_parents,
|
||||
id, layout);
|
||||
if (IS_ERR(hw))
|
||||
continue;
|
||||
|
||||
of_clk_add_hw_provider(progclknp, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
}
|
||||
|
||||
static void __init of_at91rm9200_clk_prog_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_prog_setup(np, &at91rm9200_programmable_layout);
|
||||
}
|
||||
CLK_OF_DECLARE(at91rm9200_clk_prog, "atmel,at91rm9200-clk-programmable",
|
||||
of_at91rm9200_clk_prog_setup);
|
||||
|
||||
static void __init of_at91sam9g45_clk_prog_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_prog_setup(np, &at91sam9g45_programmable_layout);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9g45_clk_prog, "atmel,at91sam9g45-clk-programmable",
|
||||
of_at91sam9g45_clk_prog_setup);
|
||||
|
||||
static void __init of_at91sam9x5_clk_prog_setup(struct device_node *np)
|
||||
{
|
||||
of_at91_clk_prog_setup(np, &at91sam9x5_programmable_layout);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9x5_clk_prog, "atmel,at91sam9x5-clk-programmable",
|
||||
of_at91sam9x5_clk_prog_setup);
|
||||
|
||||
static void __init of_at91sam9260_clk_slow_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
const char *parent_names[2];
|
||||
unsigned int num_parents;
|
||||
const char *name = np->name;
|
||||
struct regmap *regmap;
|
||||
|
||||
num_parents = of_clk_get_parent_count(np);
|
||||
if (num_parents != 2)
|
||||
return;
|
||||
|
||||
of_clk_parent_fill(np, parent_names, num_parents);
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
hw = at91_clk_register_sam9260_slow(regmap, name, parent_names,
|
||||
num_parents);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9260_clk_slow, "atmel,at91sam9260-clk-slow",
|
||||
of_at91sam9260_clk_slow_setup);
|
||||
|
||||
#ifdef CONFIG_HAVE_AT91_SMD
|
||||
#define SMD_SOURCE_MAX 2
|
||||
|
||||
static void __init of_at91sam9x5_clk_smd_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
unsigned int num_parents;
|
||||
const char *parent_names[SMD_SOURCE_MAX];
|
||||
const char *name = np->name;
|
||||
struct regmap *regmap;
|
||||
|
||||
num_parents = of_clk_get_parent_count(np);
|
||||
if (num_parents == 0 || num_parents > SMD_SOURCE_MAX)
|
||||
return;
|
||||
|
||||
of_clk_parent_fill(np, parent_names, num_parents);
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
hw = at91sam9x5_clk_register_smd(regmap, name, parent_names,
|
||||
num_parents);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9x5_clk_smd, "atmel,at91sam9x5-clk-smd",
|
||||
of_at91sam9x5_clk_smd_setup);
|
||||
#endif /* CONFIG_HAVE_AT91_SMD */
|
||||
|
||||
static void __init of_at91rm9200_clk_sys_setup(struct device_node *np)
|
||||
{
|
||||
int num;
|
||||
u32 id;
|
||||
struct clk_hw *hw;
|
||||
const char *name;
|
||||
struct device_node *sysclknp;
|
||||
const char *parent_name;
|
||||
struct regmap *regmap;
|
||||
|
||||
num = of_get_child_count(np);
|
||||
if (num > (SYSTEM_MAX_ID + 1))
|
||||
return;
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
for_each_child_of_node(np, sysclknp) {
|
||||
if (of_property_read_u32(sysclknp, "reg", &id))
|
||||
continue;
|
||||
|
||||
if (of_property_read_string(np, "clock-output-names", &name))
|
||||
name = sysclknp->name;
|
||||
|
||||
parent_name = of_clk_get_parent_name(sysclknp, 0);
|
||||
|
||||
hw = at91_clk_register_system(regmap, name, parent_name, id);
|
||||
if (IS_ERR(hw))
|
||||
continue;
|
||||
|
||||
of_clk_add_hw_provider(sysclknp, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
}
|
||||
CLK_OF_DECLARE(at91rm9200_clk_sys, "atmel,at91rm9200-clk-system",
|
||||
of_at91rm9200_clk_sys_setup);
|
||||
|
||||
#ifdef CONFIG_HAVE_AT91_USB_CLK
|
||||
#define USB_SOURCE_MAX 2
|
||||
|
||||
static void __init of_at91sam9x5_clk_usb_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
unsigned int num_parents;
|
||||
const char *parent_names[USB_SOURCE_MAX];
|
||||
const char *name = np->name;
|
||||
struct regmap *regmap;
|
||||
|
||||
num_parents = of_clk_get_parent_count(np);
|
||||
if (num_parents == 0 || num_parents > USB_SOURCE_MAX)
|
||||
return;
|
||||
|
||||
of_clk_parent_fill(np, parent_names, num_parents);
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
hw = at91sam9x5_clk_register_usb(regmap, name, parent_names,
|
||||
num_parents);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9x5_clk_usb, "atmel,at91sam9x5-clk-usb",
|
||||
of_at91sam9x5_clk_usb_setup);
|
||||
|
||||
static void __init of_at91sam9n12_clk_usb_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
const char *parent_name;
|
||||
const char *name = np->name;
|
||||
struct regmap *regmap;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
if (!parent_name)
|
||||
return;
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
hw = at91sam9n12_clk_register_usb(regmap, name, parent_name);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9n12_clk_usb, "atmel,at91sam9n12-clk-usb",
|
||||
of_at91sam9n12_clk_usb_setup);
|
||||
|
||||
static void __init of_at91rm9200_clk_usb_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
const char *parent_name;
|
||||
const char *name = np->name;
|
||||
u32 divisors[4] = {0, 0, 0, 0};
|
||||
struct regmap *regmap;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
if (!parent_name)
|
||||
return;
|
||||
|
||||
of_property_read_u32_array(np, "atmel,clk-divisors", divisors, 4);
|
||||
if (!divisors[0])
|
||||
return;
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
regmap = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
hw = at91rm9200_clk_register_usb(regmap, name, parent_name, divisors);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(at91rm9200_clk_usb, "atmel,at91rm9200-clk-usb",
|
||||
of_at91rm9200_clk_usb_setup);
|
||||
#endif /* CONFIG_HAVE_AT91_USB_CLK */
|
||||
|
||||
#ifdef CONFIG_HAVE_AT91_UTMI
|
||||
static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
const char *parent_name;
|
||||
const char *name = np->name;
|
||||
struct regmap *regmap_pmc, *regmap_sfr;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
regmap_pmc = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(regmap_pmc))
|
||||
return;
|
||||
|
||||
/*
|
||||
* If the device supports different mainck rates, this value has to be
|
||||
* set in the UTMI Clock Trimming register.
|
||||
* - 9x5: mainck supports several rates but it is indicated that a
|
||||
* 12 MHz is needed in case of USB.
|
||||
* - sama5d3 and sama5d2: mainck supports several rates. Configuring
|
||||
* the FREQ field of the UTMI Clock Trimming register is mandatory.
|
||||
* - sama5d4: mainck is at 12 MHz.
|
||||
*
|
||||
* We only need to retrieve sama5d3 or sama5d2 sfr regmap.
|
||||
*/
|
||||
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d3-sfr");
|
||||
if (IS_ERR(regmap_sfr)) {
|
||||
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
|
||||
if (IS_ERR(regmap_sfr))
|
||||
regmap_sfr = NULL;
|
||||
}
|
||||
|
||||
hw = at91_clk_register_utmi(regmap_pmc, regmap_sfr, name, parent_name);
|
||||
if (IS_ERR(hw))
|
||||
return;
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9x5_clk_utmi, "atmel,at91sam9x5-clk-utmi",
|
||||
of_at91sam9x5_clk_utmi_setup);
|
||||
#endif /* CONFIG_HAVE_AT91_UTMI */
|
@ -19,6 +19,8 @@
|
||||
|
||||
#include <asm/proc-fns.h>
|
||||
|
||||
#include <dt-bindings/clock/at91.h>
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
#define PMC_MAX_IDS 128
|
||||
@ -47,6 +49,82 @@ int of_at91_get_clk_range(struct device_node *np, const char *propname,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_at91_get_clk_range);
|
||||
|
||||
struct clk_hw *of_clk_hw_pmc_get(struct of_phandle_args *clkspec, void *data)
|
||||
{
|
||||
unsigned int type = clkspec->args[0];
|
||||
unsigned int idx = clkspec->args[1];
|
||||
struct pmc_data *pmc_data = data;
|
||||
|
||||
switch (type) {
|
||||
case PMC_TYPE_CORE:
|
||||
if (idx < pmc_data->ncore)
|
||||
return pmc_data->chws[idx];
|
||||
break;
|
||||
case PMC_TYPE_SYSTEM:
|
||||
if (idx < pmc_data->nsystem)
|
||||
return pmc_data->shws[idx];
|
||||
break;
|
||||
case PMC_TYPE_PERIPHERAL:
|
||||
if (idx < pmc_data->nperiph)
|
||||
return pmc_data->phws[idx];
|
||||
break;
|
||||
case PMC_TYPE_GCK:
|
||||
if (idx < pmc_data->ngck)
|
||||
return pmc_data->ghws[idx];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
pr_err("%s: invalid type (%u) or index (%u)\n", __func__, type, idx);
|
||||
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
void pmc_data_free(struct pmc_data *pmc_data)
|
||||
{
|
||||
kfree(pmc_data->chws);
|
||||
kfree(pmc_data->shws);
|
||||
kfree(pmc_data->phws);
|
||||
kfree(pmc_data->ghws);
|
||||
}
|
||||
|
||||
struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
|
||||
unsigned int nperiph, unsigned int ngck)
|
||||
{
|
||||
struct pmc_data *pmc_data = kzalloc(sizeof(*pmc_data), GFP_KERNEL);
|
||||
|
||||
if (!pmc_data)
|
||||
return NULL;
|
||||
|
||||
pmc_data->ncore = ncore;
|
||||
pmc_data->chws = kcalloc(ncore, sizeof(struct clk_hw *), GFP_KERNEL);
|
||||
if (!pmc_data->chws)
|
||||
goto err;
|
||||
|
||||
pmc_data->nsystem = nsystem;
|
||||
pmc_data->shws = kcalloc(nsystem, sizeof(struct clk_hw *), GFP_KERNEL);
|
||||
if (!pmc_data->shws)
|
||||
goto err;
|
||||
|
||||
pmc_data->nperiph = nperiph;
|
||||
pmc_data->phws = kcalloc(nperiph, sizeof(struct clk_hw *), GFP_KERNEL);
|
||||
if (!pmc_data->phws)
|
||||
goto err;
|
||||
|
||||
pmc_data->ngck = ngck;
|
||||
pmc_data->ghws = kcalloc(ngck, sizeof(struct clk_hw *), GFP_KERNEL);
|
||||
if (!pmc_data->ghws)
|
||||
goto err;
|
||||
|
||||
return pmc_data;
|
||||
|
||||
err:
|
||||
pmc_data_free(pmc_data);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static struct regmap *pmcreg;
|
||||
|
||||
|
@ -19,6 +19,17 @@
|
||||
|
||||
extern spinlock_t pmc_pcr_lock;
|
||||
|
||||
struct pmc_data {
|
||||
unsigned int ncore;
|
||||
struct clk_hw **chws;
|
||||
unsigned int nsystem;
|
||||
struct clk_hw **shws;
|
||||
unsigned int nperiph;
|
||||
struct clk_hw **phws;
|
||||
unsigned int ngck;
|
||||
struct clk_hw **ghws;
|
||||
};
|
||||
|
||||
struct clk_range {
|
||||
unsigned long min;
|
||||
unsigned long max;
|
||||
@ -26,9 +37,157 @@ struct clk_range {
|
||||
|
||||
#define CLK_RANGE(MIN, MAX) {.min = MIN, .max = MAX,}
|
||||
|
||||
struct clk_master_layout {
|
||||
u32 mask;
|
||||
u8 pres_shift;
|
||||
};
|
||||
|
||||
extern const struct clk_master_layout at91rm9200_master_layout;
|
||||
extern const struct clk_master_layout at91sam9x5_master_layout;
|
||||
|
||||
struct clk_master_characteristics {
|
||||
struct clk_range output;
|
||||
u32 divisors[4];
|
||||
u8 have_div3_pres;
|
||||
};
|
||||
|
||||
struct clk_pll_layout {
|
||||
u32 pllr_mask;
|
||||
u16 mul_mask;
|
||||
u8 mul_shift;
|
||||
};
|
||||
|
||||
extern const struct clk_pll_layout at91rm9200_pll_layout;
|
||||
extern const struct clk_pll_layout at91sam9g45_pll_layout;
|
||||
extern const struct clk_pll_layout at91sam9g20_pllb_layout;
|
||||
extern const struct clk_pll_layout sama5d3_pll_layout;
|
||||
|
||||
struct clk_pll_characteristics {
|
||||
struct clk_range input;
|
||||
int num_output;
|
||||
struct clk_range *output;
|
||||
u16 *icpll;
|
||||
u8 *out;
|
||||
};
|
||||
|
||||
struct clk_programmable_layout {
|
||||
u8 pres_shift;
|
||||
u8 css_mask;
|
||||
u8 have_slck_mck;
|
||||
};
|
||||
|
||||
extern const struct clk_programmable_layout at91rm9200_programmable_layout;
|
||||
extern const struct clk_programmable_layout at91sam9g45_programmable_layout;
|
||||
extern const struct clk_programmable_layout at91sam9x5_programmable_layout;
|
||||
|
||||
#define ndck(a, s) (a[s - 1].id + 1)
|
||||
#define nck(a) (a[ARRAY_SIZE(a) - 1].id + 1)
|
||||
struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
|
||||
unsigned int nperiph, unsigned int ngck);
|
||||
void pmc_data_free(struct pmc_data *pmc_data);
|
||||
|
||||
int of_at91_get_clk_range(struct device_node *np, const char *propname,
|
||||
struct clk_range *range);
|
||||
|
||||
struct clk_hw *of_clk_hw_pmc_get(struct of_phandle_args *clkspec, void *data);
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_audio_pll_frac(struct regmap *regmap, const char *name,
|
||||
const char *parent_name);
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_audio_pll_pad(struct regmap *regmap, const char *name,
|
||||
const char *parent_name);
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_audio_pll_pmc(struct regmap *regmap, const char *name,
|
||||
const char *parent_name);
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
|
||||
const char *name, const char **parent_names,
|
||||
u8 num_parents, u8 id, bool pll_audio,
|
||||
const struct clk_range *range);
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_h32mx(struct regmap *regmap, const char *name,
|
||||
const char *parent_name);
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_i2s_mux_register(struct regmap *regmap, const char *name,
|
||||
const char * const *parent_names,
|
||||
unsigned int num_parents, u8 bus_id);
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_main_rc_osc(struct regmap *regmap, const char *name,
|
||||
u32 frequency, u32 accuracy);
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_main_osc(struct regmap *regmap, const char *name,
|
||||
const char *parent_name, bool bypass);
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_rm9200_main(struct regmap *regmap,
|
||||
const char *name,
|
||||
const char *parent_name);
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_sam9x5_main(struct regmap *regmap, const char *name,
|
||||
const char **parent_names, int num_parents);
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_master(struct regmap *regmap, const char *name,
|
||||
int num_parents, const char **parent_names,
|
||||
const struct clk_master_layout *layout,
|
||||
const struct clk_master_characteristics *characteristics);
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_peripheral(struct regmap *regmap, const char *name,
|
||||
const char *parent_name, u32 id);
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
|
||||
const char *name, const char *parent_name,
|
||||
u32 id, const struct clk_range *range);
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_pll(struct regmap *regmap, const char *name,
|
||||
const char *parent_name, u8 id,
|
||||
const struct clk_pll_layout *layout,
|
||||
const struct clk_pll_characteristics *characteristics);
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_plldiv(struct regmap *regmap, const char *name,
|
||||
const char *parent_name);
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_programmable(struct regmap *regmap, const char *name,
|
||||
const char **parent_names, u8 num_parents, u8 id,
|
||||
const struct clk_programmable_layout *layout);
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_sam9260_slow(struct regmap *regmap,
|
||||
const char *name,
|
||||
const char **parent_names,
|
||||
int num_parents);
|
||||
|
||||
struct clk_hw * __init
|
||||
at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name,
|
||||
const char **parent_names, u8 num_parents);
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_system(struct regmap *regmap, const char *name,
|
||||
const char *parent_name, u8 id);
|
||||
|
||||
struct clk_hw * __init
|
||||
at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
|
||||
const char **parent_names, u8 num_parents);
|
||||
struct clk_hw * __init
|
||||
at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name,
|
||||
const char *parent_name);
|
||||
struct clk_hw * __init
|
||||
at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
|
||||
const char *parent_name, const u32 *divisors);
|
||||
|
||||
struct clk_hw * __init
|
||||
at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
|
||||
const char *name, const char *parent_name);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
void pmc_register_id(u8 id);
|
||||
void pmc_register_pck(u8 pck);
|
||||
|
336
drivers/clk/at91/sama5d2.c
Normal file
336
drivers/clk/at91/sama5d2.c
Normal file
@ -0,0 +1,336 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dt-bindings/clock/at91.h>
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
static const struct clk_master_characteristics mck_characteristics = {
|
||||
.output = { .min = 124000000, .max = 166000000 },
|
||||
.divisors = { 1, 2, 4, 3 },
|
||||
};
|
||||
|
||||
static u8 plla_out[] = { 0 };
|
||||
|
||||
static u16 plla_icpll[] = { 0 };
|
||||
|
||||
static struct clk_range plla_outputs[] = {
|
||||
{ .min = 600000000, .max = 1200000000 },
|
||||
};
|
||||
|
||||
static const struct clk_pll_characteristics plla_characteristics = {
|
||||
.input = { .min = 12000000, .max = 12000000 },
|
||||
.num_output = ARRAY_SIZE(plla_outputs),
|
||||
.output = plla_outputs,
|
||||
.icpll = plla_icpll,
|
||||
.out = plla_out,
|
||||
};
|
||||
|
||||
static const struct {
|
||||
char *n;
|
||||
char *p;
|
||||
u8 id;
|
||||
} sama5d2_systemck[] = {
|
||||
{ .n = "ddrck", .p = "masterck", .id = 2 },
|
||||
{ .n = "lcdck", .p = "masterck", .id = 3 },
|
||||
{ .n = "uhpck", .p = "usbck", .id = 6 },
|
||||
{ .n = "udpck", .p = "usbck", .id = 7 },
|
||||
{ .n = "pck0", .p = "prog0", .id = 8 },
|
||||
{ .n = "pck1", .p = "prog1", .id = 9 },
|
||||
{ .n = "pck2", .p = "prog2", .id = 10 },
|
||||
{ .n = "iscck", .p = "masterck", .id = 18 },
|
||||
};
|
||||
|
||||
static const struct {
|
||||
char *n;
|
||||
u8 id;
|
||||
struct clk_range r;
|
||||
} sama5d2_periph32ck[] = {
|
||||
{ .n = "macb0_clk", .id = 5, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "tdes_clk", .id = 11, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "matrix1_clk", .id = 14, },
|
||||
{ .n = "hsmc_clk", .id = 17, },
|
||||
{ .n = "pioA_clk", .id = 18, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "flx0_clk", .id = 19, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "flx1_clk", .id = 20, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "flx2_clk", .id = 21, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "flx3_clk", .id = 22, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "flx4_clk", .id = 23, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "uart0_clk", .id = 24, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "uart1_clk", .id = 25, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "uart2_clk", .id = 26, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "uart3_clk", .id = 27, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "uart4_clk", .id = 28, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "twi0_clk", .id = 29, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "twi1_clk", .id = 30, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "spi0_clk", .id = 33, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "spi1_clk", .id = 34, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "tcb0_clk", .id = 35, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "tcb1_clk", .id = 36, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "pwm_clk", .id = 38, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "adc_clk", .id = 40, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "uhphs_clk", .id = 41, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "udphs_clk", .id = 42, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "ssc0_clk", .id = 43, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "ssc1_clk", .id = 44, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "trng_clk", .id = 47, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "pdmic_clk", .id = 48, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "securam_clk", .id = 51, },
|
||||
{ .n = "i2s0_clk", .id = 54, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "i2s1_clk", .id = 55, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "can0_clk", .id = 56, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "can1_clk", .id = 57, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "classd_clk", .id = 59, .r = { .min = 0, .max = 83000000 }, },
|
||||
};
|
||||
|
||||
static const struct {
|
||||
char *n;
|
||||
u8 id;
|
||||
} sama5d2_periphck[] = {
|
||||
{ .n = "dma0_clk", .id = 6, },
|
||||
{ .n = "dma1_clk", .id = 7, },
|
||||
{ .n = "aes_clk", .id = 9, },
|
||||
{ .n = "aesb_clk", .id = 10, },
|
||||
{ .n = "sha_clk", .id = 12, },
|
||||
{ .n = "mpddr_clk", .id = 13, },
|
||||
{ .n = "matrix0_clk", .id = 15, },
|
||||
{ .n = "sdmmc0_hclk", .id = 31, },
|
||||
{ .n = "sdmmc1_hclk", .id = 32, },
|
||||
{ .n = "lcdc_clk", .id = 45, },
|
||||
{ .n = "isc_clk", .id = 46, },
|
||||
{ .n = "qspi0_clk", .id = 52, },
|
||||
{ .n = "qspi1_clk", .id = 53, },
|
||||
};
|
||||
|
||||
static const struct {
|
||||
char *n;
|
||||
u8 id;
|
||||
struct clk_range r;
|
||||
bool pll;
|
||||
} sama5d2_gck[] = {
|
||||
{ .n = "sdmmc0_gclk", .id = 31, },
|
||||
{ .n = "sdmmc1_gclk", .id = 32, },
|
||||
{ .n = "tcb0_gclk", .id = 35, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "tcb1_gclk", .id = 36, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "pwm_gclk", .id = 38, .r = { .min = 0, .max = 83000000 }, },
|
||||
{ .n = "isc_gclk", .id = 46, },
|
||||
{ .n = "pdmic_gclk", .id = 48, },
|
||||
{ .n = "i2s0_gclk", .id = 54, .pll = true },
|
||||
{ .n = "i2s1_gclk", .id = 55, .pll = true },
|
||||
{ .n = "can0_gclk", .id = 56, .r = { .min = 0, .max = 80000000 }, },
|
||||
{ .n = "can1_gclk", .id = 57, .r = { .min = 0, .max = 80000000 }, },
|
||||
{ .n = "classd_gclk", .id = 59, .r = { .min = 0, .max = 100000000 },
|
||||
.pll = true },
|
||||
};
|
||||
|
||||
static void __init sama5d2_pmc_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_range range = CLK_RANGE(0, 0);
|
||||
const char *slck_name, *mainxtal_name;
|
||||
struct pmc_data *sama5d2_pmc;
|
||||
const char *parent_names[6];
|
||||
struct regmap *regmap, *regmap_sfr;
|
||||
struct clk_hw *hw;
|
||||
int i;
|
||||
bool bypass;
|
||||
|
||||
i = of_property_match_string(np, "clock-names", "slow_clk");
|
||||
if (i < 0)
|
||||
return;
|
||||
|
||||
slck_name = of_clk_get_parent_name(np, i);
|
||||
|
||||
i = of_property_match_string(np, "clock-names", "main_xtal");
|
||||
if (i < 0)
|
||||
return;
|
||||
mainxtal_name = of_clk_get_parent_name(np, i);
|
||||
|
||||
regmap = syscon_node_to_regmap(np);
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
sama5d2_pmc = pmc_data_allocate(PMC_I2S1_MUX + 1,
|
||||
nck(sama5d2_systemck),
|
||||
nck(sama5d2_periph32ck),
|
||||
nck(sama5d2_gck));
|
||||
if (!sama5d2_pmc)
|
||||
return;
|
||||
|
||||
hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
|
||||
100000000);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
bypass = of_property_read_bool(np, "atmel,osc-bypass");
|
||||
|
||||
hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
|
||||
bypass);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
parent_names[0] = "main_rc_osc";
|
||||
parent_names[1] = "main_osc";
|
||||
hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d2_pmc->chws[PMC_MAIN] = hw;
|
||||
|
||||
hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
|
||||
&sama5d3_pll_layout, &plla_characteristics);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_plldiv(regmap, "plladivck", "pllack");
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_audio_pll_frac(regmap, "audiopll_fracck",
|
||||
"mainck");
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_audio_pll_pad(regmap, "audiopll_padck",
|
||||
"audiopll_fracck");
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_audio_pll_pmc(regmap, "audiopll_pmcck",
|
||||
"audiopll_fracck");
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
|
||||
if (IS_ERR(regmap_sfr))
|
||||
regmap_sfr = NULL;
|
||||
|
||||
hw = at91_clk_register_utmi(regmap, regmap_sfr, "utmick", "mainck");
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d2_pmc->chws[PMC_UTMI] = hw;
|
||||
|
||||
parent_names[0] = slck_name;
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
parent_names[3] = "utmick";
|
||||
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
|
||||
&at91sam9x5_master_layout,
|
||||
&mck_characteristics);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d2_pmc->chws[PMC_MCK] = hw;
|
||||
|
||||
hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck");
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d2_pmc->chws[PMC_MCK2] = hw;
|
||||
|
||||
parent_names[0] = "plladivck";
|
||||
parent_names[1] = "utmick";
|
||||
hw = at91sam9x5_clk_register_usb(regmap, "usbck", parent_names, 2);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
parent_names[0] = slck_name;
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
parent_names[3] = "utmick";
|
||||
parent_names[4] = "mck";
|
||||
for (i = 0; i < 3; i++) {
|
||||
char name[6];
|
||||
|
||||
snprintf(name, sizeof(name), "prog%d", i);
|
||||
|
||||
hw = at91_clk_register_programmable(regmap, name,
|
||||
parent_names, 5, i,
|
||||
&at91sam9x5_programmable_layout);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sama5d2_systemck); i++) {
|
||||
hw = at91_clk_register_system(regmap, sama5d2_systemck[i].n,
|
||||
sama5d2_systemck[i].p,
|
||||
sama5d2_systemck[i].id);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d2_pmc->shws[sama5d2_systemck[i].id] = hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sama5d2_periphck); i++) {
|
||||
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
|
||||
sama5d2_periphck[i].n,
|
||||
"masterck",
|
||||
sama5d2_periphck[i].id,
|
||||
&range);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d2_pmc->phws[sama5d2_periphck[i].id] = hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sama5d2_periph32ck); i++) {
|
||||
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
|
||||
sama5d2_periph32ck[i].n,
|
||||
"h32mxck",
|
||||
sama5d2_periph32ck[i].id,
|
||||
&sama5d2_periph32ck[i].r);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d2_pmc->phws[sama5d2_periph32ck[i].id] = hw;
|
||||
}
|
||||
|
||||
parent_names[0] = slck_name;
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
parent_names[3] = "utmick";
|
||||
parent_names[4] = "mck";
|
||||
parent_names[5] = "audiopll_pmcck";
|
||||
for (i = 0; i < ARRAY_SIZE(sama5d2_gck); i++) {
|
||||
hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
|
||||
sama5d2_gck[i].n,
|
||||
parent_names, 6,
|
||||
sama5d2_gck[i].id,
|
||||
sama5d2_gck[i].pll,
|
||||
&sama5d2_gck[i].r);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d2_pmc->ghws[sama5d2_gck[i].id] = hw;
|
||||
}
|
||||
|
||||
if (regmap_sfr) {
|
||||
parent_names[0] = "i2s0_clk";
|
||||
parent_names[1] = "i2s0_gclk";
|
||||
hw = at91_clk_i2s_mux_register(regmap_sfr, "i2s0_muxclk",
|
||||
parent_names, 2, 0);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d2_pmc->chws[PMC_I2S0_MUX] = hw;
|
||||
|
||||
parent_names[0] = "i2s1_clk";
|
||||
parent_names[1] = "i2s1_gclk";
|
||||
hw = at91_clk_i2s_mux_register(regmap_sfr, "i2s1_muxclk",
|
||||
parent_names, 2, 1);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d2_pmc->chws[PMC_I2S1_MUX] = hw;
|
||||
}
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sama5d2_pmc);
|
||||
|
||||
return;
|
||||
|
||||
err_free:
|
||||
pmc_data_free(sama5d2_pmc);
|
||||
}
|
||||
CLK_OF_DECLARE_DRIVER(sama5d2_pmc, "atmel,sama5d2-pmc", sama5d2_pmc_setup);
|
264
drivers/clk/at91/sama5d4.c
Normal file
264
drivers/clk/at91/sama5d4.c
Normal file
@ -0,0 +1,264 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dt-bindings/clock/at91.h>
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
static const struct clk_master_characteristics mck_characteristics = {
|
||||
.output = { .min = 125000000, .max = 200000000 },
|
||||
.divisors = { 1, 2, 4, 3 },
|
||||
};
|
||||
|
||||
static u8 plla_out[] = { 0 };
|
||||
|
||||
static u16 plla_icpll[] = { 0 };
|
||||
|
||||
static struct clk_range plla_outputs[] = {
|
||||
{ .min = 600000000, .max = 1200000000 },
|
||||
};
|
||||
|
||||
static const struct clk_pll_characteristics plla_characteristics = {
|
||||
.input = { .min = 12000000, .max = 12000000 },
|
||||
.num_output = ARRAY_SIZE(plla_outputs),
|
||||
.output = plla_outputs,
|
||||
.icpll = plla_icpll,
|
||||
.out = plla_out,
|
||||
};
|
||||
|
||||
static const struct {
|
||||
char *n;
|
||||
char *p;
|
||||
u8 id;
|
||||
} sama5d4_systemck[] = {
|
||||
{ .n = "ddrck", .p = "masterck", .id = 2 },
|
||||
{ .n = "lcdck", .p = "masterck", .id = 3 },
|
||||
{ .n = "smdck", .p = "smdclk", .id = 4 },
|
||||
{ .n = "uhpck", .p = "usbck", .id = 6 },
|
||||
{ .n = "udpck", .p = "usbck", .id = 7 },
|
||||
{ .n = "pck0", .p = "prog0", .id = 8 },
|
||||
{ .n = "pck1", .p = "prog1", .id = 9 },
|
||||
{ .n = "pck2", .p = "prog2", .id = 10 },
|
||||
};
|
||||
|
||||
static const struct {
|
||||
char *n;
|
||||
u8 id;
|
||||
} sama5d4_periph32ck[] = {
|
||||
{ .n = "pioD_clk", .id = 5 },
|
||||
{ .n = "usart0_clk", .id = 6 },
|
||||
{ .n = "usart1_clk", .id = 7 },
|
||||
{ .n = "icm_clk", .id = 9 },
|
||||
{ .n = "aes_clk", .id = 12 },
|
||||
{ .n = "tdes_clk", .id = 14 },
|
||||
{ .n = "sha_clk", .id = 15 },
|
||||
{ .n = "matrix1_clk", .id = 17 },
|
||||
{ .n = "hsmc_clk", .id = 22 },
|
||||
{ .n = "pioA_clk", .id = 23 },
|
||||
{ .n = "pioB_clk", .id = 24 },
|
||||
{ .n = "pioC_clk", .id = 25 },
|
||||
{ .n = "pioE_clk", .id = 26 },
|
||||
{ .n = "uart0_clk", .id = 27 },
|
||||
{ .n = "uart1_clk", .id = 28 },
|
||||
{ .n = "usart2_clk", .id = 29 },
|
||||
{ .n = "usart3_clk", .id = 30 },
|
||||
{ .n = "usart4_clk", .id = 31 },
|
||||
{ .n = "twi0_clk", .id = 32 },
|
||||
{ .n = "twi1_clk", .id = 33 },
|
||||
{ .n = "twi2_clk", .id = 34 },
|
||||
{ .n = "mci0_clk", .id = 35 },
|
||||
{ .n = "mci1_clk", .id = 36 },
|
||||
{ .n = "spi0_clk", .id = 37 },
|
||||
{ .n = "spi1_clk", .id = 38 },
|
||||
{ .n = "spi2_clk", .id = 39 },
|
||||
{ .n = "tcb0_clk", .id = 40 },
|
||||
{ .n = "tcb1_clk", .id = 41 },
|
||||
{ .n = "tcb2_clk", .id = 42 },
|
||||
{ .n = "pwm_clk", .id = 43 },
|
||||
{ .n = "adc_clk", .id = 44 },
|
||||
{ .n = "dbgu_clk", .id = 45 },
|
||||
{ .n = "uhphs_clk", .id = 46 },
|
||||
{ .n = "udphs_clk", .id = 47 },
|
||||
{ .n = "ssc0_clk", .id = 48 },
|
||||
{ .n = "ssc1_clk", .id = 49 },
|
||||
{ .n = "trng_clk", .id = 53 },
|
||||
{ .n = "macb0_clk", .id = 54 },
|
||||
{ .n = "macb1_clk", .id = 55 },
|
||||
{ .n = "fuse_clk", .id = 57 },
|
||||
{ .n = "securam_clk", .id = 59 },
|
||||
{ .n = "smd_clk", .id = 61 },
|
||||
{ .n = "twi3_clk", .id = 62 },
|
||||
{ .n = "catb_clk", .id = 63 },
|
||||
};
|
||||
|
||||
static const struct {
|
||||
char *n;
|
||||
u8 id;
|
||||
} sama5d4_periphck[] = {
|
||||
{ .n = "dma0_clk", .id = 8 },
|
||||
{ .n = "cpkcc_clk", .id = 10 },
|
||||
{ .n = "aesb_clk", .id = 13 },
|
||||
{ .n = "mpddr_clk", .id = 16 },
|
||||
{ .n = "matrix0_clk", .id = 18 },
|
||||
{ .n = "vdec_clk", .id = 19 },
|
||||
{ .n = "dma1_clk", .id = 50 },
|
||||
{ .n = "lcdc_clk", .id = 51 },
|
||||
{ .n = "isi_clk", .id = 52 },
|
||||
};
|
||||
|
||||
static void __init sama5d4_pmc_setup(struct device_node *np)
|
||||
{
|
||||
struct clk_range range = CLK_RANGE(0, 0);
|
||||
const char *slck_name, *mainxtal_name;
|
||||
struct pmc_data *sama5d4_pmc;
|
||||
const char *parent_names[5];
|
||||
struct regmap *regmap;
|
||||
struct clk_hw *hw;
|
||||
int i;
|
||||
bool bypass;
|
||||
|
||||
i = of_property_match_string(np, "clock-names", "slow_clk");
|
||||
if (i < 0)
|
||||
return;
|
||||
|
||||
slck_name = of_clk_get_parent_name(np, i);
|
||||
|
||||
i = of_property_match_string(np, "clock-names", "main_xtal");
|
||||
if (i < 0)
|
||||
return;
|
||||
mainxtal_name = of_clk_get_parent_name(np, i);
|
||||
|
||||
regmap = syscon_node_to_regmap(np);
|
||||
if (IS_ERR(regmap))
|
||||
return;
|
||||
|
||||
sama5d4_pmc = pmc_data_allocate(PMC_MCK2 + 1,
|
||||
nck(sama5d4_systemck),
|
||||
nck(sama5d4_periph32ck), 0);
|
||||
if (!sama5d4_pmc)
|
||||
return;
|
||||
|
||||
hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
|
||||
100000000);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
bypass = of_property_read_bool(np, "atmel,osc-bypass");
|
||||
|
||||
hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
|
||||
bypass);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
parent_names[0] = "main_rc_osc";
|
||||
parent_names[1] = "main_osc";
|
||||
hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
|
||||
&sama5d3_pll_layout, &plla_characteristics);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_plldiv(regmap, "plladivck", "pllack");
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d4_pmc->chws[PMC_UTMI] = hw;
|
||||
|
||||
parent_names[0] = slck_name;
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
parent_names[3] = "utmick";
|
||||
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
|
||||
&at91sam9x5_master_layout,
|
||||
&mck_characteristics);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d4_pmc->chws[PMC_MCK] = hw;
|
||||
|
||||
hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck");
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d4_pmc->chws[PMC_MCK2] = hw;
|
||||
|
||||
parent_names[0] = "plladivck";
|
||||
parent_names[1] = "utmick";
|
||||
hw = at91sam9x5_clk_register_usb(regmap, "usbck", parent_names, 2);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
parent_names[0] = "plladivck";
|
||||
parent_names[1] = "utmick";
|
||||
hw = at91sam9x5_clk_register_smd(regmap, "smdclk", parent_names, 2);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
parent_names[0] = slck_name;
|
||||
parent_names[1] = "mainck";
|
||||
parent_names[2] = "plladivck";
|
||||
parent_names[3] = "utmick";
|
||||
parent_names[4] = "mck";
|
||||
for (i = 0; i < 3; i++) {
|
||||
char name[6];
|
||||
|
||||
snprintf(name, sizeof(name), "prog%d", i);
|
||||
|
||||
hw = at91_clk_register_programmable(regmap, name,
|
||||
parent_names, 5, i,
|
||||
&at91sam9x5_programmable_layout);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sama5d4_systemck); i++) {
|
||||
hw = at91_clk_register_system(regmap, sama5d4_systemck[i].n,
|
||||
sama5d4_systemck[i].p,
|
||||
sama5d4_systemck[i].id);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d4_pmc->shws[sama5d4_systemck[i].id] = hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sama5d4_periphck); i++) {
|
||||
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
|
||||
sama5d4_periphck[i].n,
|
||||
"masterck",
|
||||
sama5d4_periphck[i].id,
|
||||
&range);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d4_pmc->phws[sama5d4_periphck[i].id] = hw;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sama5d4_periph32ck); i++) {
|
||||
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
|
||||
sama5d4_periph32ck[i].n,
|
||||
"h32mxck",
|
||||
sama5d4_periph32ck[i].id,
|
||||
&range);
|
||||
if (IS_ERR(hw))
|
||||
goto err_free;
|
||||
|
||||
sama5d4_pmc->phws[sama5d4_periph32ck[i].id] = hw;
|
||||
}
|
||||
|
||||
of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sama5d4_pmc);
|
||||
|
||||
return;
|
||||
|
||||
err_free:
|
||||
pmc_data_free(sama5d4_pmc);
|
||||
}
|
||||
CLK_OF_DECLARE_DRIVER(sama5d4_pmc, "atmel,sama5d4-pmc", sama5d4_pmc_setup);
|
@ -94,7 +94,7 @@ struct clk *imx_clk_cpu(const char *name, const char *parent_name,
|
||||
|
||||
init.name = name;
|
||||
init.ops = &clk_cpu_ops;
|
||||
init.flags = 0;
|
||||
init.flags = CLK_IS_CRITICAL;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
|
||||
|
@ -379,14 +379,6 @@ static const char *pll_enet_bypass_sel[] = { "pll_enet_main", "pll_enet_main_src
|
||||
static const char *pll_audio_bypass_sel[] = { "pll_audio_main", "pll_audio_main_src", };
|
||||
static const char *pll_video_bypass_sel[] = { "pll_video_main", "pll_video_main_src", };
|
||||
|
||||
static int const clks_init_on[] __initconst = {
|
||||
IMX7D_ARM_A7_ROOT_CLK, IMX7D_MAIN_AXI_ROOT_CLK,
|
||||
IMX7D_PLL_SYS_MAIN_480M_CLK, IMX7D_NAND_USDHC_BUS_ROOT_CLK,
|
||||
IMX7D_DRAM_PHYM_ROOT_CLK, IMX7D_DRAM_ROOT_CLK,
|
||||
IMX7D_DRAM_PHYM_ALT_ROOT_CLK, IMX7D_DRAM_ALT_ROOT_CLK,
|
||||
IMX7D_AHB_CHANNEL_ROOT_CLK, IMX7D_IPG_ROOT_CLK,
|
||||
};
|
||||
|
||||
static struct clk_onecell_data clk_data;
|
||||
|
||||
static struct clk ** const uart_clks[] __initconst = {
|
||||
@ -404,7 +396,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
|
||||
{
|
||||
struct device_node *np;
|
||||
void __iomem *base;
|
||||
int i;
|
||||
|
||||
clks[IMX7D_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
|
||||
clks[IMX7D_OSC_24M_CLK] = of_clk_get_by_name(ccm_node, "osc");
|
||||
@ -467,7 +458,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
|
||||
clks[IMX7D_PLL_SYS_MAIN_120M] = imx_clk_fixed_factor("pll_sys_main_120m", "pll_sys_main_clk", 1, 4);
|
||||
clks[IMX7D_PLL_DRAM_MAIN_533M] = imx_clk_fixed_factor("pll_dram_533m", "pll_dram_main_clk", 1, 2);
|
||||
|
||||
clks[IMX7D_PLL_SYS_MAIN_480M_CLK] = imx_clk_gate_dis("pll_sys_main_480m_clk", "pll_sys_main_480m", base + 0xb0, 4);
|
||||
clks[IMX7D_PLL_SYS_MAIN_480M_CLK] = imx_clk_gate_dis_flags("pll_sys_main_480m_clk", "pll_sys_main_480m", base + 0xb0, 4, CLK_IS_CRITICAL);
|
||||
clks[IMX7D_PLL_SYS_MAIN_240M_CLK] = imx_clk_gate_dis("pll_sys_main_240m_clk", "pll_sys_main_240m", base + 0xb0, 5);
|
||||
clks[IMX7D_PLL_SYS_MAIN_120M_CLK] = imx_clk_gate_dis("pll_sys_main_120m_clk", "pll_sys_main_120m", base + 0xb0, 6);
|
||||
clks[IMX7D_PLL_DRAM_MAIN_533M_CLK] = imx_clk_gate("pll_dram_533m_clk", "pll_dram_533m", base + 0x70, 12);
|
||||
@ -720,7 +711,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
|
||||
clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider2("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6);
|
||||
clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_divider2("nand_usdhc_root_clk", "nand_usdhc_pre_div", base + 0x8980, 0, 6);
|
||||
clks[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_divider2("ahb_root_clk", "ahb_pre_div", base + 0x9000, 0, 6);
|
||||
clks[IMX7D_IPG_ROOT_CLK] = imx_clk_divider2("ipg_root_clk", "ahb_root_clk", base + 0x9080, 0, 2);
|
||||
clks[IMX7D_IPG_ROOT_CLK] = imx_clk_divider_flags("ipg_root_clk", "ahb_root_clk", base + 0x9080, 0, 2, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_PARENT);
|
||||
clks[IMX7D_DRAM_ROOT_DIV] = imx_clk_divider2("dram_post_div", "dram_cg", base + 0x9880, 0, 3);
|
||||
clks[IMX7D_DRAM_PHYM_ALT_ROOT_DIV] = imx_clk_divider2("dram_phym_alt_post_div", "dram_phym_alt_pre_div", base + 0xa000, 0, 3);
|
||||
clks[IMX7D_DRAM_ALT_ROOT_DIV] = imx_clk_divider2("dram_alt_post_div", "dram_alt_pre_div", base + 0xa080, 0, 3);
|
||||
@ -784,17 +775,17 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
|
||||
clks[IMX7D_CLKO1_ROOT_DIV] = imx_clk_divider2("clko1_post_div", "clko1_pre_div", base + 0xbd80, 0, 6);
|
||||
clks[IMX7D_CLKO2_ROOT_DIV] = imx_clk_divider2("clko2_post_div", "clko2_pre_div", base + 0xbe00, 0, 6);
|
||||
|
||||
clks[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_gate4("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0);
|
||||
clks[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_gate2_flags("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0, CLK_OPS_PARENT_ENABLE);
|
||||
clks[IMX7D_ARM_M4_ROOT_CLK] = imx_clk_gate4("arm_m4_root_clk", "arm_m4_div", base + 0x4010, 0);
|
||||
clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate4("main_axi_root_clk", "axi_post_div", base + 0x4040, 0);
|
||||
clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate2_flags("main_axi_root_clk", "axi_post_div", base + 0x4040, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
|
||||
clks[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_gate4("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0);
|
||||
clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate4("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0);
|
||||
clks[IMX7D_OCRAM_CLK] = imx_clk_gate4("ocram_clk", "main_axi_root_clk", base + 0x4110, 0);
|
||||
clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate4("ocram_s_clk", "ahb_root_clk", base + 0x4120, 0);
|
||||
clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate4("dram_root_clk", "dram_post_div", base + 0x4130, 0);
|
||||
clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0);
|
||||
clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate4("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0);
|
||||
clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate4("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0);
|
||||
clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate2_flags("dram_root_clk", "dram_post_div", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
|
||||
clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate2_flags("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
|
||||
clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate2_flags("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
|
||||
clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate2_flags("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
|
||||
clks[IMX7D_OCOTP_CLK] = imx_clk_gate4("ocotp_clk", "ipg_root_clk", base + 0x4230, 0);
|
||||
clks[IMX7D_SNVS_CLK] = imx_clk_gate4("snvs_clk", "ipg_root_clk", base + 0x4250, 0);
|
||||
clks[IMX7D_MU_ROOT_CLK] = imx_clk_gate4("mu_root_clk", "ipg_root_clk", base + 0x4270, 0);
|
||||
@ -883,9 +874,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
|
||||
clk_data.clk_num = ARRAY_SIZE(clks);
|
||||
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
|
||||
clk_prepare_enable(clks[clks_init_on[i]]);
|
||||
|
||||
clk_set_parent(clks[IMX7D_PLL_ARM_MAIN_BYPASS], clks[IMX7D_PLL_ARM_MAIN]);
|
||||
clk_set_parent(clks[IMX7D_PLL_DRAM_MAIN_BYPASS], clks[IMX7D_PLL_DRAM_MAIN]);
|
||||
clk_set_parent(clks[IMX7D_PLL_SYS_MAIN_BYPASS], clks[IMX7D_PLL_SYS_MAIN]);
|
||||
|
@ -137,6 +137,13 @@ static inline struct clk *imx_clk_gate_dis(const char *name, const char *parent,
|
||||
shift, CLK_GATE_SET_TO_DISABLE, &imx_ccm_lock);
|
||||
}
|
||||
|
||||
static inline struct clk *imx_clk_gate_dis_flags(const char *name, const char *parent,
|
||||
void __iomem *reg, u8 shift, unsigned long flags)
|
||||
{
|
||||
return clk_register_gate(NULL, name, parent, flags | CLK_SET_RATE_PARENT, reg,
|
||||
shift, CLK_GATE_SET_TO_DISABLE, &imx_ccm_lock);
|
||||
}
|
||||
|
||||
static inline struct clk *imx_clk_gate2(const char *name, const char *parent,
|
||||
void __iomem *reg, u8 shift)
|
||||
{
|
||||
|
@ -227,8 +227,8 @@ static struct mmp_param_gate_clk apmu_gate_clks[] = {
|
||||
/* The gate clocks has mux parent. */
|
||||
{MMP2_CLK_SDH0, "sdh0_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH0, 0x1b, 0x1b, 0x0, 0, &sdh_lock},
|
||||
{MMP2_CLK_SDH1, "sdh1_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH1, 0x1b, 0x1b, 0x0, 0, &sdh_lock},
|
||||
{MMP2_CLK_SDH1, "sdh2_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH2, 0x1b, 0x1b, 0x0, 0, &sdh_lock},
|
||||
{MMP2_CLK_SDH1, "sdh3_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH3, 0x1b, 0x1b, 0x0, 0, &sdh_lock},
|
||||
{MMP2_CLK_SDH2, "sdh2_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH2, 0x1b, 0x1b, 0x0, 0, &sdh_lock},
|
||||
{MMP2_CLK_SDH3, "sdh3_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH3, 0x1b, 0x1b, 0x0, 0, &sdh_lock},
|
||||
{MMP2_CLK_DISP0, "disp0_clk", "disp0_div", CLK_SET_RATE_PARENT, APMU_DISP0, 0x1b, 0x1b, 0x0, 0, &disp0_lock},
|
||||
{MMP2_CLK_DISP0_SPHY, "disp0_sphy_clk", "disp0_sphy_div", CLK_SET_RATE_PARENT, APMU_DISP0, 0x1024, 0x1024, 0x0, 0, &disp0_lock},
|
||||
{MMP2_CLK_DISP1, "disp1_clk", "disp1_div", CLK_SET_RATE_PARENT, APMU_DISP1, 0x1b, 0x1b, 0x0, 0, &disp1_lock},
|
||||
|
@ -9,6 +9,20 @@
|
||||
#ifndef _DT_BINDINGS_CLK_AT91_H
|
||||
#define _DT_BINDINGS_CLK_AT91_H
|
||||
|
||||
#define PMC_TYPE_CORE 0
|
||||
#define PMC_TYPE_SYSTEM 1
|
||||
#define PMC_TYPE_PERIPHERAL 2
|
||||
#define PMC_TYPE_GCK 3
|
||||
|
||||
#define PMC_SLOW 0
|
||||
#define PMC_MCK 1
|
||||
#define PMC_UTMI 2
|
||||
#define PMC_MAIN 3
|
||||
#define PMC_MCK2 4
|
||||
#define PMC_I2S0_MUX 5
|
||||
#define PMC_I2S1_MUX 6
|
||||
|
||||
#ifndef AT91_PMC_MOSCS
|
||||
#define AT91_PMC_MOSCS 0 /* MOSCS Flag */
|
||||
#define AT91_PMC_LOCKA 1 /* PLLA Lock */
|
||||
#define AT91_PMC_LOCKB 2 /* PLLB Lock */
|
||||
@ -19,5 +33,6 @@
|
||||
#define AT91_PMC_MOSCRCS 17 /* Main On-Chip RC */
|
||||
#define AT91_PMC_CFDEV 18 /* Clock Failure Detector Event */
|
||||
#define AT91_PMC_GCKRDY 24 /* Generated Clocks */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
34
include/dt-bindings/reset/actions,s700-reset.h
Normal file
34
include/dt-bindings/reset/actions,s700-reset.h
Normal file
@ -0,0 +1,34 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
|
||||
//
|
||||
// Device Tree binding constants for Actions Semi S700 Reset Management Unit
|
||||
//
|
||||
// Copyright (c) 2018 Linaro Ltd.
|
||||
|
||||
#ifndef __DT_BINDINGS_ACTIONS_S700_RESET_H
|
||||
#define __DT_BINDINGS_ACTIONS_S700_RESET_H
|
||||
|
||||
#define RESET_AUDIO 0
|
||||
#define RESET_CSI 1
|
||||
#define RESET_DE 2
|
||||
#define RESET_DSI 3
|
||||
#define RESET_GPIO 4
|
||||
#define RESET_I2C0 5
|
||||
#define RESET_I2C1 6
|
||||
#define RESET_I2C2 7
|
||||
#define RESET_I2C3 8
|
||||
#define RESET_KEY 9
|
||||
#define RESET_LCD0 10
|
||||
#define RESET_SI 11
|
||||
#define RESET_SPI0 12
|
||||
#define RESET_SPI1 13
|
||||
#define RESET_SPI2 14
|
||||
#define RESET_SPI3 15
|
||||
#define RESET_UART0 16
|
||||
#define RESET_UART1 17
|
||||
#define RESET_UART2 18
|
||||
#define RESET_UART3 19
|
||||
#define RESET_UART4 20
|
||||
#define RESET_UART5 21
|
||||
#define RESET_UART6 22
|
||||
|
||||
#endif /* __DT_BINDINGS_ACTIONS_S700_RESET_H */
|
65
include/dt-bindings/reset/actions,s900-reset.h
Normal file
65
include/dt-bindings/reset/actions,s900-reset.h
Normal file
@ -0,0 +1,65 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
|
||||
//
|
||||
// Device Tree binding constants for Actions Semi S900 Reset Management Unit
|
||||
//
|
||||
// Copyright (c) 2018 Linaro Ltd.
|
||||
|
||||
#ifndef __DT_BINDINGS_ACTIONS_S900_RESET_H
|
||||
#define __DT_BINDINGS_ACTIONS_S900_RESET_H
|
||||
|
||||
#define RESET_CHIPID 0
|
||||
#define RESET_CPU_SCNT 1
|
||||
#define RESET_SRAMI 2
|
||||
#define RESET_DDR_CTL_PHY 3
|
||||
#define RESET_DMAC 4
|
||||
#define RESET_GPIO 5
|
||||
#define RESET_BISP_AXI 6
|
||||
#define RESET_CSI0 7
|
||||
#define RESET_CSI1 8
|
||||
#define RESET_DE 9
|
||||
#define RESET_DSI 10
|
||||
#define RESET_GPU3D_PA 11
|
||||
#define RESET_GPU3D_PB 12
|
||||
#define RESET_HDE 13
|
||||
#define RESET_I2C0 14
|
||||
#define RESET_I2C1 15
|
||||
#define RESET_I2C2 16
|
||||
#define RESET_I2C3 17
|
||||
#define RESET_I2C4 18
|
||||
#define RESET_I2C5 19
|
||||
#define RESET_IMX 20
|
||||
#define RESET_NANDC0 21
|
||||
#define RESET_NANDC1 22
|
||||
#define RESET_SD0 23
|
||||
#define RESET_SD1 24
|
||||
#define RESET_SD2 25
|
||||
#define RESET_SD3 26
|
||||
#define RESET_SPI0 27
|
||||
#define RESET_SPI1 28
|
||||
#define RESET_SPI2 29
|
||||
#define RESET_SPI3 30
|
||||
#define RESET_UART0 31
|
||||
#define RESET_UART1 32
|
||||
#define RESET_UART2 33
|
||||
#define RESET_UART3 34
|
||||
#define RESET_UART4 35
|
||||
#define RESET_UART5 36
|
||||
#define RESET_UART6 37
|
||||
#define RESET_HDMI 38
|
||||
#define RESET_LVDS 39
|
||||
#define RESET_EDP 40
|
||||
#define RESET_USB2HUB 41
|
||||
#define RESET_USB2HSIC 42
|
||||
#define RESET_USB3 43
|
||||
#define RESET_PCM1 44
|
||||
#define RESET_AUDIO 45
|
||||
#define RESET_PCM0 46
|
||||
#define RESET_SE 47
|
||||
#define RESET_GIC 48
|
||||
#define RESET_DDR_CTL_PHY_AXI 49
|
||||
#define RESET_CMU_DDR 50
|
||||
#define RESET_DMM 51
|
||||
#define RESET_HDCP2TX 52
|
||||
#define RESET_ETHERNET 53
|
||||
|
||||
#endif /* __DT_BINDINGS_ACTIONS_S900_RESET_H */
|
Loading…
Reference in New Issue
Block a user