[PATCH 2/3] peci: aspeed: Auto calculate the adapter divisor
Joel Stanley
joel at jms.id.au
Wed Oct 28 15:40:22 AEDT 2020
Hi Billy,
On Fri, 16 Oct 2020 at 06:26, Billy Tsai <billy_tsai at aspeedtech.com> wrote:
>
> This pach change the meaning of clk-frequency property from original
> controller clock to bit frequency of peci negotiation stage and auto
> calculate the adapter divisor setting to close aim.
> The expected frequency and real frequency may have errors because of the
> granularities of the divisor.
This patch can't go to the mainline lists as the authors (Intel) have
not yet had it merged.
Cheers,
Joel
>
> Signed-off-by: Billy Tsai <billy_tsai at aspeedtech.com>
> ---
> arch/arm/boot/dts/aspeed-g6.dtsi | 4 +-
> drivers/peci/busses/peci-aspeed.c | 91 ++++++++++++++++++-------------
> 2 files changed, 53 insertions(+), 42 deletions(-)
>
> diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
> index cb053a996e87..6e1e5b5733e6 100644
> --- a/arch/arm/boot/dts/aspeed-g6.dtsi
> +++ b/arch/arm/boot/dts/aspeed-g6.dtsi
> @@ -750,9 +750,7 @@
> interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
> clocks = <&syscon ASPEED_CLK_GATE_REF0CLK>;
> resets = <&syscon ASPEED_RESET_PECI>;
> - clock-frequency = <24000000>;
> - msg-timing = <1>;
> - addr-timing = <1>;
> + clock-frequency = <1000000>;
> rd-sampling-point = <8>;
> cmd-timeout-ms = <1000>;
> status = "disabled";
> diff --git a/drivers/peci/busses/peci-aspeed.c b/drivers/peci/busses/peci-aspeed.c
> index d6039b1c4494..9e7c7582e4bb 100644
> --- a/drivers/peci/busses/peci-aspeed.c
> +++ b/drivers/peci/busses/peci-aspeed.c
> @@ -133,6 +133,11 @@
> #define ASPEED_PECI_64B_R_DATAE 0xF8
> #define ASPEED_PECI_64B_R_DATAF 0xFC
>
> +/* Bus Frequency */
> +#define ASPEED_PECI_BUS_FREQ_MAX 2000000
> +#define ASPEED_PECI_BUS_FREQ_MIN 2000
> +#define ASPEED_PECI_BUS_FREQ_DEFAULT 1000000
> +
> /* Timing Negotiation */
> #define ASPEED_PECI_RD_SAMPLING_POINT_DEFAULT 8
> #define ASPEED_PECI_RD_SAMPLING_POINT_MAX 15
> @@ -324,51 +329,47 @@ static irqreturn_t aspeed_peci_irq_handler(int irq, void *arg)
> static int aspeed_peci_init_ctrl(struct aspeed_peci *priv)
> {
> u32 msg_timing, addr_timing, rd_sampling_point;
> - u32 clk_freq, clk_divisor, clk_div_val = 0;
> + u32 clk_freq, clk_div_val = 0;
> + u32 msg_timing_idx, clk_div_val_idx;
> + int delta_value, delta_tmp, clk_divisor, clk_divisor_tmp;
> int ret;
>
> - priv->clk = devm_clk_get(priv->dev, NULL);
> - if (IS_ERR(priv->clk)) {
> - dev_err(priv->dev, "Failed to get clk source.\n");
> - return PTR_ERR(priv->clk);
> - }
> -
> - ret = clk_prepare_enable(priv->clk);
> - if (ret) {
> - dev_err(priv->dev, "Failed to enable clock.\n");
> - return ret;
> - }
> -
> ret = device_property_read_u32(priv->dev, "clock-frequency", &clk_freq);
> - if (ret) {
> - dev_err(priv->dev,
> - "Could not read clock-frequency property.\n");
> - clk_disable_unprepare(priv->clk);
> - return ret;
> - }
> -
> - clk_divisor = clk_get_rate(priv->clk) / clk_freq;
> -
> - while ((clk_divisor >> 1) && (clk_div_val < ASPEED_PECI_CLK_DIV_MAX))
> - clk_div_val++;
> -
> - ret = device_property_read_u32(priv->dev, "msg-timing", &msg_timing);
> - if (ret || msg_timing > ASPEED_PECI_MSG_TIMING_MAX) {
> + if (ret ||
> + clk_freq > ASPEED_PECI_BUS_FREQ_MAX ||
> + clk_freq < ASPEED_PECI_BUS_FREQ_MIN) {
> if (!ret)
> dev_warn(priv->dev,
> - "Invalid msg-timing : %u, Use default : %u\n",
> - msg_timing, ASPEED_PECI_MSG_TIMING_DEFAULT);
> - msg_timing = ASPEED_PECI_MSG_TIMING_DEFAULT;
> - }
> -
> - ret = device_property_read_u32(priv->dev, "addr-timing", &addr_timing);
> - if (ret || addr_timing > ASPEED_PECI_ADDR_TIMING_MAX) {
> - if (!ret)
> - dev_warn(priv->dev,
> - "Invalid addr-timing : %u, Use default : %u\n",
> - addr_timing, ASPEED_PECI_ADDR_TIMING_DEFAULT);
> - addr_timing = ASPEED_PECI_ADDR_TIMING_DEFAULT;
> + "Invalid clock-frequency : %u, Use default : %u\n",
> + clk_freq, ASPEED_PECI_BUS_FREQ_DEFAULT);
> + clk_freq = ASPEED_PECI_BUS_FREQ_DEFAULT;
> }
> + /*
> + * PECI bus clock = (Ref. clk) / (1 << PECI00[10:8])
> + * PECI operation clock = (PECI bus clock)/ 4*(PECI04[15:8]*4+1)
> + * (1 << PECI00[10:8]) * (PECI04[15:8]*4+1) =
> + * (Ref. clk) / (4 * PECI operation clock)
> + */
> + clk_divisor = clk_get_rate(priv->clk) / (4*clk_freq);
> + delta_value = clk_divisor;
> + /* Find the closest divisor for clock-frequency */
> + for (msg_timing_idx = 1; msg_timing_idx <= 255; msg_timing_idx++)
> + for (clk_div_val_idx = 0; clk_div_val_idx < 7;
> + clk_div_val_idx++) {
> + clk_divisor_tmp = (1 << clk_div_val_idx) *
> + (msg_timing_idx * 4 + 1);
> + delta_tmp = abs(clk_divisor - clk_divisor_tmp);
> + if (delta_tmp < delta_value) {
> + delta_value = delta_tmp;
> + msg_timing = msg_timing_idx;
> + clk_div_val = clk_div_val_idx;
> + }
> + }
> + addr_timing = msg_timing;
> + dev_info(priv->dev, "Expect frequency: %d Real frequency is about: %lu",
> + clk_freq,
> + clk_get_rate(priv->clk) /
> + (4 * (1 << clk_div_val) * (msg_timing * 4 + 1)));
>
> ret = device_property_read_u32(priv->dev, "rd-sampling-point",
> &rd_sampling_point);
> @@ -463,6 +464,18 @@ static int aspeed_peci_probe(struct platform_device *pdev)
> priv->adapter->xfer = aspeed_peci_xfer;
> priv->adapter->use_dma = false;
>
> + priv->clk = devm_clk_get(priv->dev, NULL);
> + if (IS_ERR(priv->clk)) {
> + dev_err(priv->dev, "Failed to get clk source.\n");
> + return PTR_ERR(priv->clk);
> + }
> +
> + ret = clk_prepare_enable(priv->clk);
> + if (ret) {
> + dev_err(priv->dev, "Failed to enable clock.\n");
> + return ret;
> + }
> +
> priv->rst = devm_reset_control_get(&pdev->dev, NULL);
> if (IS_ERR(priv->rst)) {
> dev_err(&pdev->dev,
> --
> 2.17.1
>
More information about the Linux-aspeed
mailing list