Skip to content

Commit 64c437d

Browse files
author
deooi
committed
pl35x-nand-controller: Enable dynamic clk rate setting
Bluefin devices require different clk frequencies to be set at different timing modes. Enable the memclk rate to be set according to the specifications in the device tree. If the device tree does not have this memclk-timing-frequency property specified, the driver proceeds as usual. Signed-off-by: deooi <deborah.ooi@ni.com>
1 parent 1d286b1 commit 64c437d

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

arch/arm/boot/dts/xilinx/ni-zynq.dtsi

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,16 @@
140140

141141
&smcc {
142142
status = "okay";
143+
/*
144+
* Bluefin devices require different memclk frequency
145+
* for different timing modes
146+
*/
147+
memclk-timing-frequency = <0 83333333>,
148+
<1 166666666>,
149+
<2 166666666>,
150+
<3 166666666>,
151+
<4 166666666>,
152+
<5 166666666>;
143153
};
144154

145155
&nfc0 {

drivers/mtd/nand/raw/pl35x-nand-controller.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,28 @@ static int pl35x_nfc_exec_op(struct nand_chip *chip,
795795
op, check_only);
796796
}
797797

798+
static unsigned long of_get_memclk_freq(const struct device_node *np, const int timing_mode)
799+
{
800+
int memclk_frequency, i, total_elements = 0;
801+
u32 memclk_mode;
802+
803+
total_elements = of_property_count_u32_elems(np, "memclk-timing-frequency");
804+
if (!total_elements)
805+
return 0;
806+
807+
for (i = 0; i < total_elements; i = i+2) {
808+
of_property_read_u32_index(np, "memclk-timing-frequency", i, &memclk_mode);
809+
if (memclk_mode == timing_mode) {
810+
of_property_read_u32_index(np, "memclk-timing-frequency",
811+
i+1, &memclk_frequency);
812+
return memclk_frequency;
813+
}
814+
}
815+
816+
pr_err("Failed to find matching timing mode %d\n", timing_mode);
817+
return 0;
818+
}
819+
798820
static int pl35x_nfc_setup_interface(struct nand_chip *chip, int cs,
799821
const struct nand_interface_config *conf)
800822
{
@@ -804,6 +826,8 @@ static int pl35x_nfc_setup_interface(struct nand_chip *chip, int cs,
804826
const struct nand_sdr_timings *sdr;
805827
unsigned int period_ns, val;
806828
struct clk *mclk;
829+
unsigned long memclk_of_timing_freq;
830+
int ret = 0;
807831

808832
sdr = nand_get_sdr_timings(conf);
809833
if (IS_ERR(sdr))
@@ -815,6 +839,23 @@ static int pl35x_nfc_setup_interface(struct nand_chip *chip, int cs,
815839
return PTR_ERR(mclk);
816840
}
817841

842+
/*
843+
* Bluefin devices require different rates for different timing modes
844+
* so we need to set the rate according to the timing modes
845+
*/
846+
memclk_of_timing_freq = of_get_memclk_freq(
847+
nfc->dev->parent->of_node,
848+
conf->timings.mode);
849+
850+
if (memclk_of_timing_freq) {
851+
ret = clk_set_rate(mclk, memclk_of_timing_freq);
852+
if (ret) {
853+
pr_err("Failed to set memclk timing frequency to %lu\n",
854+
memclk_of_timing_freq);
855+
return ret;
856+
}
857+
}
858+
818859
/*
819860
* SDR timings are given in pico-seconds while NFC timings must be
820861
* expressed in NAND controller clock cycles. We use the TO_CYCLE()

0 commit comments

Comments
 (0)